目录
InnoDB是一款平衡高可靠性和高性能的通用存储引擎。在MySQL 5.7中,InnoDB是默认的MySQL存储引擎。除非您配置了其他默认存储引擎,否则发出CREATE
TABLE不带ENGINE=
子句的语句会创建一个InnoDB表。
其DML操作遵循 ACID模型, 具有 提交, 回滚和 崩溃恢复 功能的事务保护用户数据。有关更多信息,请参见 第14.2节“InnoDB和ACID模型”。
行级锁定和Oracle样式的一致读取提高了多用户并发性和性能。有关更多信息,请参见第14.5节“InnoDB锁定和事务模型”。
InnoDB表将您的数据安排在磁盘上以优化基于主键的查询
。每个
InnoDB表都有一个主键索引,称为聚集索引
,它组织数据以最大限度地减少主键查找的I / O。有关更多信息,请参见第14.8.2.1节“集群索引和二级索引”。
为了维护数据
完整性,
InnoDB支持
FOREIGN
KEY约束。使用外键时,将检查插入,更新和删除操作,以确保它们不会导致不同表之间的不一致。有关更多信息,请参见
第14.8.1.6节“InnoDB和FOREIGN KEY约束”。
表14.1 InnoDB存储引擎功能
| 特征 | 支持 |
|---|---|
| B树索引 | 是 |
| 备份/时间点恢复(在服务器中实施,而不是在存储引擎中实施。) | 是 |
| 集群数据库支持 | 没有 |
| 聚集索引 | 是 |
| 压缩数据 | 是 |
| 数据缓存 | 是 |
| 加密数据(通过加密功能在服务器中实现。静态数据表空间加密在MySQL 5.7和更高版本中可用。) | 是 |
| 外键支持 | 是 |
| 全文搜索索引 | 是的(InnoDB对FULLTEXT索引的支持在MySQL 5.6和更高版本中可用。) |
| 地理空间数据类型支持 | 是 |
| 地理空间索引支持 | 是的(InnoDB对地理空间索引的支持在MySQL 5.7和更高版本中可用。) |
| 哈希索引 | 否(InnoDB在其内部使用散列索引来实现自适应散列索引功能。) |
| 索引缓存 | 是 |
| 锁定粒度 | 行 |
| MVCC | 是 |
| 查询缓存支持 | 是 |
| 复制支持(在服务器中实现,而不是在存储引擎中实现。) | 是 |
| 存储限制 | 64TB |
| T树索引 | 没有 |
| 交易 | 是 |
| 更新数据字典的统计信息 | 是 |
要比较InnoDB随MySQL提供的其他存储引擎的功能,请参阅第15章备用存储引擎中的存储引擎功能表
。
有关InnoDB增强功能和新功能的信息,请参阅:
第1.4节“MySQL 5.7中的新增InnoDB功能”中
的增强列表
。
该 发行说明。
有关InnoDB相关术语和定义,请参阅MySQL术语表。
有关InnoDB存储引擎的论坛,请参阅
MySQL论坛:: InnoDB。
InnoDB以MySQL的相同GNU GPL许可证版本2(1991年6月)发布。有关MySQL授权的更多信息,请参阅
http://www.mysql.com/company/legal/licensing/。
您可能会发现有InnoDB利于以下原因的表格:
如果您的服务器因硬件或软件问题而崩溃,无论当时数据库中发生了什么情况,重新启动数据库后无需执行任何特殊操作。InnoDB
崩溃恢复会
自动完成崩溃前提交的任何更改,并撤消所有正在处理但未提交的更改。只需重新启动并继续你离开的地方。
该InnoDB存储引擎维护它自己的
缓冲池,当数据被访问主内存中缓存表和索引数据。常用数据直接从内存中处理。此缓存适用于许多类型的信息并加速处理。在专用数据库服务器上,经常将高达80%的物理内存分配给缓冲池。
如果将相关数据分解到不同的表中,则可以设置 强制执行 参照完整性的外键。更新或删除数据,其他表中的相关数据会自动更新或删除。尝试将数据插入辅助表中,而主表中没有相应的数据,并且错误的数据会自动踢出。
如果数据在磁盘或内存中损坏,则在使用它之前, 校验和机制会提醒您使用伪造数据。
当您为每个表使用适当的主键列设计数据库时
,涉及这些列的操作会自动进行优化。引用WHERE
子句,ORDER
BY子句,
GROUP BY
子句和连接操作中的主键列是非常快的
。
插入,更新和删除通过称为变更缓冲的自动机制进行优化。InnoDB不仅可以对同一个表进行并发读取和写入访问,还可以缓存更改的数据以简化磁盘I / O。
性能优势不限于具有长时间运行查询的巨型表。当从表中反复访问相同的行时,称为 自适应哈希索引的功能会继续执行,以使这些查找更快,就像它们从哈希表中出来一样。
您可以压缩表和关联的索引。
您可以创建和删除索引,而对性能和可用性影响更小。
截断每个表的
文件表
空间非常快,可以腾出磁盘空间供操作系统重复使用,而不是释放系统表空间中只能InnoDB重用的空间。
您可以通过查询INFORMATION_SCHEMA 表来监视存储引擎的内部运作情况 。
您可以通过查询性能架构表来监控存储引擎的性能细节 。
InnoDB即使在相同的语句中,
您也可以自由地将表与来自其他MySQL存储引擎的表混合。例如,您可以使用
连接操作将单个查询中的数据InnoDB和
MEMORY表中的数据组合在一起。
InnoDB 设计用于处理大量数据时的CPU效率和最高性能。
InnoDB 即使在文件大小限制为2GB的操作系统上,表格也可以处理大量数据。
对于InnoDB您可以在您的应用程序代码中应用的特定调优技术,请参见
第8.5节“优化InnoDB表”。
本节介绍使用InnoDB表格时的最佳做法
。
根据来自这些表的相同ID值从多个表中提取数据的地方 使用连接。为了加快连接性能,请在连接列上定义 外键,并在每个表中声明具有相同数据类型的列。添加外键可确保引用的列进行索引,从而提高性能。外键还传播删除或更新所有受影响的表,并防止在父表中不存在相应的ID时将数据插入到子表中。
关闭自动提交。每秒提交数百次会限制性能(受存储设备写入速度的限制)。
分组组相关的DML
操作成
交易,通过包围他们START TRANSACTION和
COMMIT报表。虽然你不想过于频繁地提交,你也不想发出的巨大的批次
INSERT,
UPDATE或者
DELETE,如果没有犯了几个小时运行的语句。
不使用LOCK TABLES
语句。InnoDB可以一次处理多个会话全部读取和写入同一个表,而不会牺牲可靠性或高性能。要获得对一组行的独占写权限,请使用
SELECT
... FOR UPDATE语法来锁定您想要更新的行。
启用该
innodb_file_per_table选项或使用常规表空间将表的数据和索引放入单独的文件中,而不是
系统表空间。
该innodb_file_per_table
选项默认启用。
评估您的数据和访问模式是否受益于InnoDB表或页面
压缩功能。您可以压缩InnoDB表而不牺牲读/写功能。
使用选项运行服务器,
--sql_mode=NO_ENGINE_SUBSTITUTION
以防止使用其他存储引擎创建表时,如果在ENGINE=子句中
指定的引擎有问题
CREATE TABLE。
发表SHOW ENGINES声明以查看可用的MySQL存储引擎。寻找
DEFAULT在InnoDB行。
mysql> SHOW ENGINES;
或者,查询
INFORMATION_SCHEMA.ENGINES表格。
mysql> SELECT * FROM INFORMATION_SCHEMA.ENGINES;
如果InnoDB不是您的默认存储引擎,您可以InnoDB通过--default-storage-engine=InnoDB
在命令行中default-storage-engine=innodb
定义或者
在[mysqld]MySQL服务器选项文件部分中定义的重新启动服务器
来确定数据库服务器或应用程序是否正常工作。
由于更改默认存储引擎只会在创建新表时影响新表,请运行所有应用程序安装和设置步骤以确认所有事情都已正确安装。然后练习所有的应用程序功能,以确保所有数据加载,编辑和查询功能都能正常工作。如果表依赖于特定于其他存储引擎的功能,则会收到错误; 将该
子句添加
到
语句以避免错误。
ENGINE=other_engine_nameCREATE TABLE
如果您没有仔细决定存储引擎,并且想要预览某些表在创建时如何工作InnoDB,请ALTER TABLE
table_name ENGINE=InnoDB;为每个表发出命令
。或者,要运行测试查询和其他语句而不干扰原始表格,请复制一份:
CREATE TABLE InnoDB_Table(...)ENGINE = InnoDB AS SELECT * FROM other_engine_table;
要在真实工作负载下评估完整应用程序的性能,请安装最新的MySQL服务器并运行基准测试。
测试完整的应用程序生命周期,从安装到大量使用和服务器重新启动。在数据库繁忙期间终止服务器进程以模拟电源故障,并在重新启动服务器时验证数据是否已成功恢复。
测试任何复制配置,特别是如果您在主服务器和从服务器上使用不同的MySQL版本和选项。
Oracle建议InnoDB将其作为典型数据库应用程序的首选存储引擎,从单一用户维基和本地系统上运行的博客到推动性能极限的高端应用程序。在MySQL 5.7中,InnoDB是新表的默认存储引擎。
InnoDB不能被禁用。该
--skip-innodb
选项已被弃用且无效,其使用会导致警告。它将在未来的MySQL版本中被删除。这也适用于它的同义词(--innodb=OFF,
--disable-innodb,等)。
该ACID模式是一组数据库设计原则强调的是,对于业务数据和关键任务应用重要的可靠性方面。MySQL包含的组件如InnoDB存储引擎紧密结合ACID模型,以便数据不被破坏,并且结果不会因特殊情况(如软件崩溃和硬件故障)而失真。当您依赖ACID兼容功能时,您不需要重新发明一致性检查和崩溃恢复机制。如果您有其他软件保护措施,超可靠硬件或可以容忍少量数据丢失或不一致的应用程序,则可以调整MySQL设置以交换部分ACID可靠性以获得更高的性能或吞吐量。
以下各节讨论MySQL功能(特别是InnoDB存储引擎)如何
与ACID模型的类别进行交互:
答:原子性。
C:一致性。
我......隔离。
D:耐久性。
ACID模型
的原子性方面主要涉及InnoDB
交易。相关的MySQL功能包括:
ACID模型
的一致性方面主要涉及内部InnoDB处理以保护数据免受崩溃。相关的MySQL功能包括:
ACID模型
的隔离方面主要涉及InnoDB
事务,特别是适用于每个事务的隔离级别。相关的MySQL功能包括:
ACID模型 的耐久性方面涉及MySQL软件功能与您的特定硬件配置进行交互。由于CPU,网络和存储设备的功能有很多可能性,因此提供具体的指导方针是最复杂的。(这些指南可能采取购买“ 新硬件 ”的形式 。)相关的MySQL功能包括:
InnoDB
双写缓冲区,由innodb_doublewrite
配置选项打开和关闭
。
配置选项
sync_binlog。
配置选项
innodb_file_per_table。
在存储设备(如磁盘驱动器,SSD或RAID阵列)中写入缓冲区。
存储设备中的电池备份缓存。
用于运行MySQL的操作系统,特别是它对fsync()系统调用的支持。
不间断电源(UPS)保护运行MySQL服务器和存储MySQL数据的所有计算机服务器和存储设备的电源。
您的备份策略,例如备份频率和类型以及备份保留期。
对于分布式或托管数据应用程序,MySQL服务器硬件所在数据中心的特定特征以及数据中心之间的网络连接。
InnoDB是一个
多版本的存储引擎:它保存有关旧版本更改行的信息,以支持事务性功能,如并发和
回滚。这些信息存储在表空间中的数据结构中,称为
回滚段(在Oracle中的类似数据结构之后)。InnoDB
使用回滚段中的信息执行事务回滚中所需的撤消操作。它还使用这些信息构建一个行的早期版本以进行
一致的读取。
在内部,InnoDB为存储在数据库中的每一行添加三个字段。一个6字节的DB_TRX_ID字段表示插入或更新行的最后一个事务的事务标识符。另外,删除在内部被视为更新,其中行中的特殊位被设置为将其标记为删除。每行还包含一个DB_ROLL_PTR称为滚动指针的7字节
字段。滚动指针指向写入回滚段的撤消日志记录。如果该行已更新,则撤消日志记录包含在更新行之前重建该行内容所需的信息。一个6字节的DB_ROW_ID字段包含一个随着新行插入而单调递增的行ID。如果
InnoDB自动生成聚集索引,该索引包含行ID值。否则,该
DB_ROW_ID列不会出现在任何索引中。
撤销日志回滚段分为插入和更新撤消日志。插入撤消日志只在事务回滚中需要,并且只要事务提交就可以丢弃。更新撤消日志也用于一致性读取,但只有当没有事务存在时才会被丢弃,该事务
InnoDB已分配了一个快照,在一致的读取中可能需要更新撤消日志中的信息来构建数据库的较早版本行。
定期提交您的交易,包括只发布一致读取的交易。否则,
InnoDB不能从更新撤消日志中丢弃数据,并且回滚段可能变得太大,从而填满你的表空间。
回滚段中撤销日志记录的物理大小通常小于相应的插入或更新行。您可以使用此信息来计算回滚段所需的空间。
在InnoDB多版本方案中,当您使用SQL语句删除行时,行不会立即从数据库中物理删除。InnoDB只有在丢弃为删除而写入的更新撤消日志记录时,才会物理删除相应的行及其索引记录。这个删除操作称为清除,它非常快,通常与删除的SQL语句的时间顺序相同。
如果您在表格中以大致相同的速率插入和删除小批量行,则清除线程可能开始滞后,并且由于所有“ 死 ”行,表可能变得越来越大
,从而使得所有的磁盘都是磁盘绑定的,而且非常慢。在这种情况下,通过调整innodb_max_purge_lag系统变量来限制新行操作,并为清除线程分配更多资源
。有关更多信息,请参见第14.14节“InnoDB启动选项和系统变量”。
InnoDB多版本并发控制(MVCC)将二级索引视为与聚簇索引不同。聚集索引中的记录在原地更新,其隐藏系统列指向撤销日志条目,从中可以重建早期版本的记录。与聚集索引记录不同,二级索引记录不包含隐藏的系统列,也不就地更新。
当辅助索引列更新时,旧的辅助索引记录将被删除标记,插入新记录,最后清除删除标记的记录。当辅助索引记录被删除标记或辅助索引页面被更新的事务更新时,InnoDB查找聚集索引中的数据库记录。在聚集索引中,DB_TRX_ID检查记录,如果记录在读取事务启动后被修改,则从撤消日志中检索正确版本的记录。
如果辅助索引记录被标记为删除或者辅助索引页面被更新的事务更新,
则不使用覆盖索引技术。而不是从索引结构返回值,InnoDB查找聚集索引中的记录。
但是,如果启用了
索引条件下推(ICP)优化,并且WHERE可以仅使用索引中的字段来评估条件的某些部分,那么MySQL服务器仍然会将这部分WHERE条件下推到存储引擎,在该存储引擎中使用指数。如果找不到匹配的记录,则避免聚集索引查找。如果找到匹配的记录,即使在删除标记的记录中,也会
InnoDB查找聚集索引中的记录。
本节介绍InnoDB存储引擎体系结构的主要组件
。
缓冲池是主存储器中的一个区域,
InnoDB用于访问作为数据的缓存表和索引数据。缓冲池允许经常使用的数据直接从内存中处理,从而加快处理速度。在专用数据库服务器上,经常将高达80%的物理内存分配给InnoDB缓冲池。
为了提高高容量读取操作的效率,缓冲池分为可能包含多行的页面。为了高速缓存管理的效率,缓冲池被实现为页面的链接列表; 很少使用的数据使用LRU算法的变体超时缓存。
有关更多信息,请参见第14.6.3.1节“InnoDB缓冲池”和第14.6.3节“InnoDB缓冲池配置”。
更改缓冲区是一种特殊的数据结构,
当受影响的页面不在缓冲池中时,缓存对辅助索引页面的
更改。缓冲的变化,这可能导致从
,
或
当页面被加载到由其他的读操作缓冲池操作(DML),将在后面合并。
INSERTUPDATEDELETE
与聚簇索引不同,二级索引通常是不唯一的,插入到二级索引中会以相对随机的顺序进行。同样,删除和更新可能会影响不相邻位于索引树中的二级索引页。稍后合并缓存更改时,受影响的页面通过其他操作读入缓冲池时,可避免从磁盘读入二级索引页面所需的大量随机访问I / O。
定期地,当系统大部分处于空闲状态或缓慢关闭期间运行的清除操作会将更新后的索引页写入磁盘。与每个值立即写入磁盘相比,清除操作可以更有效地为一系列索引值写入磁盘块。
当需要更新许多二级索引和许多受影响的行时,更改缓冲区合并可能需要几个小时。在此期间,磁盘I / O会增加,这可能会导致磁盘绑定查询的显着减速。事务提交后,更改缓冲区合并也可能继续发生。事实上,在服务器关闭和重新启动后,更改缓冲区合并可能会继续发生(请参见 第14.21.2节“强制InnoDB恢复”以获取更多信息)。
在内存中,更改缓冲区占用了InnoDB缓冲池的一部分
。在磁盘上,更改缓冲区是系统表空间的一部分,因此索引更改在数据库重新启动时保持缓冲。
缓存在更改缓冲区中的数据类型由
innodb_change_buffering
配置选项控制。有关更多信息,请参见
第14.6.5节“配置InnoDB更改缓冲”。您还可以配置最大更改缓冲区大小。有关更多信息,请参见
第14.6.5.1节“配置更改缓冲区的最大大小”。
以下选项可用于更改缓冲区监视:
InnoDB标准监视器输出包含更改缓冲区的状态信息。要查看监视器数据,请发出SHOW ENGINE INNODB STATUS
命令。
MySQL的> SHOW ENGINE INNODB STATUS\G
更改缓冲区状态信息位于INSERT BUFFER AND ADAPTIVE HASH INDEX
标题下方
并与以下内容类似:
------------------------------------- INSERT BUFFER和ADAPTIVE HASH INDEX ------------------------------------- Ibuf:大小1,空闲列表len 0,seg大小2,0合并 合并操作: 插入0,删除标记0,删除0 丢弃的操作: 插入0,删除标记0,删除0 哈希表大小4425293,使用的单元32,节点堆有1个缓冲区(s) 13577.57散列搜索/ s,202.47非散列搜索/ s
有关更多信息,请参见 第14.17.3节“InnoDB标准监视器和锁定监视器输出”。
该
INFORMATION_SCHEMA.INNODB_METRICS
表格提供了InnoDB标准监视器输出中的大部分数据点
以及其他数据点。要查看更改缓冲区度量标准及其每个描述,请发出以下查询:
MySQL的> SELECT NAME, COMMENT FROM INFORMATION_SCHEMA.INNODB_METRICS WHERE NAME LIKE '%ibuf%'\G
有关INNODB_METRICS表格使用信息,请参见
第14.15.6节“InnoDB INFORMATION_SCHEMA指标表”。
该
INFORMATION_SCHEMA.INNODB_BUFFER_PAGE
表提供有关缓冲池中每个页面的元数据,包括更改缓冲区索引和更改缓冲区位图页面。更改缓冲区页面由标识
PAGE_TYPE。IBUF_INDEX
是更改缓冲区索引页
IBUF_BITMAP的页面类型,是更改缓冲区位图页的页面类型。
查询
INNODB_BUFFER_PAGE表可能会导致显着的性能开销。为避免影响性能,请重新创建要在测试实例上调查的问题,并在测试实例上运行查询。
例如,您可以查询该
INNODB_BUFFER_PAGE表以确定大概的缓冲池页面数量
IBUF_INDEX和
IBUF_BITMAP页面总数的百分比。
MySQL的>SELECT (SELECT COUNT(*) FROM INFORMATION_SCHEMA.INNODB_BUFFER_PAGEWHERE PAGE_TYPE LIKE 'IBUF%') AS change_buffer_pages,(SELECT COUNT(*) FROM INFORMATION_SCHEMA.INNODB_BUFFER_PAGE) AS total_pages,(SELECT ((change_buffer_pages/total_pages)*100))AS change_buffer_page_percentage;+ --------------------- + ------------- ------------- + ------------------ + | change_buffer_pages | total_pages | change_buffer_page_percentage | + --------------------- + ------------- ------------- + ------------------ + | 25 | 8192 | 0.3052 | + --------------------- + ------------- ------------- + ------------------ +
有关该INNODB_BUFFER_PAGE表提供的其他数据的信息
,请参见
第24.31.1节“INFORMATION_SCHEMA INNODB_BUFFER_PAGE表”。有关相关使用信息,请参见
第14.15.5节“InnoDB INFORMATION_SCHEMA缓冲池表”。
性能架构 为高级性能监视提供了更改缓冲区互斥量等待检测。要查看更改缓冲区检测,请发出以下查询:
MySQL的>SELECT * FROM performance_schema.setup_instrumentsWHERE NAME LIKE '%wait/synch/mutex/innodb/ibuf%';+ ------------------------------------------------- ------ + --------- + ------- + | NAME | ENABLED | TIMED | + ------------------------------------------------- ------ + --------- + ------- + | wait / synch / mutex / innodb / ibuf_bitmap_mutex | 是| 是| | wait / synch / mutex / innodb / ibuf_mutex | 是| 是| | wait / synch / mutex / innodb / ibuf_pessimistic_insert_mutex | 是| 是| + ------------------------------------------------- ------ + --------- + ------- +
有关监视InnoDB
互斥等待的信息,请参见
第14.16.2节“使用性能架构监视InnoDB互斥等待”。
所述自适应散列索引(AHI)允许InnoDB执行更喜欢与工作量和用于充足存储器的适当组合,系统内存中的数据库
缓冲池,在不牺牲任何事务特性或可靠性。该功能由该innodb_adaptive_hash_index
选项启用
,或--skip-innodb_adaptive_hash_index在服务器启动时关闭
。
根据观察到的搜索模式,MySQL使用索引键的前缀构建一个哈希索引。密钥的前缀可以是任意长度,并且可能只有B树中的某些值出现在哈希索引中。哈希索引是根据需要为经常访问的索引页面构建的。
如果一张表几乎完全适用于主内存,那么散列索引可以通过直接查找任何元素来加快查询速度,从而将索引值转换为一种指针。InnoDB
有一个监视索引搜索的机制。如果
InnoDB注意到查询可以从构建散列索引中受益,它会自动执行。
对于一些工作负载,散列索引查找的加速大大超过了监视索引查找和维护散列索引结构的额外工作。有时候,保护访问自适应散列索引的读/写锁可能成为工作负载繁重的争用源,如多个并发连接。查询与
LIKE运营商和%
通配符也不会从AHI中受益。对于不需要自适应散列索引的工作负载,将其关闭可减少不必要的性能开销。因为很难提前预测此功能是否适合特定系统,请考虑使用实际工作负载来启用和禁用启用和禁用基准。MySQL 5.6和更高版本中的架构更改使适用于禁用自适应哈希索引的工作负载比早期版本更适合,但默认情况下它仍处于启用状态。
在MySQL 5.7中,自适应散列索引搜索系统是分区的。每个索引都绑定到一个特定的分区,每个分区受独立的锁存器保护。分区由innodb_adaptive_hash_index_parts
配置选项控制
。在早期版本中,自适应散列索引搜索系统受单个锁存器的保护,该锁存器在繁重的工作负载下可能成为争用点。该
innodb_adaptive_hash_index_parts
选项默认设置为8。最大设置是512。
散列索引始终基于表上现有的B树索引构建
。
InnoDB可以在为B树定义的任何密钥长度的前缀上构建一个哈希索引,具体取决于InnoDB观察到的B树索引的搜索模式。散列索引可以是部分的,仅覆盖索引经常访问的那些页面。
您可以监视自适应哈希索引的使用SEMAPHORES
以及在SHOW ENGINE INNODB
STATUS命令输出部分中
使用它的争用情况。如果看到许多线程正在等待创建的RW锁存器btr0sea.c,那么禁用自适应散列索引可能会很有用。
有关散列索引性能特征的更多信息,请参见第8.3.8节“B树和散列索引的比较”。
重做日志缓冲区是保存要写入重做日志的数据的内存区域。重做日志缓冲区大小由innodb_log_buffer_size
配置选项定义
。重做日志缓冲区会定期刷新到磁盘上的日志文件。一个大的重做日志缓冲区允许大事务运行,而无需在事务提交之前将重做日志写入磁盘。因此,如果您有更新,插入或删除多行的事务,则使日志缓冲区更大可节省磁盘I / O。
该
innodb_flush_log_at_trx_commit
选项控制如何将重做日志缓冲区的内容写入日志文件。该
innodb_flush_log_at_timeout
选项控制重做日志刷新频率。
所述InnoDB系统表空间包含的
InnoDB数据字典(元数据
InnoDB-相关对象)和对于双写缓冲器,所述缓冲器改变的存储区,并撤消日志。系统表空间还包含在系统表空间中创建的任何用户创建表的表和索引数据。系统表空间被视为共享表空间,因为它被多个表共享。
系统表空间由一个或多个数据文件表示。默认情况下,ibdata1在MySQL data目录中创建一个名为named的系统数据文件。系统数据文件的大小和数量由innodb_data_file_path启动选项控制
。
有关相关信息,请参见 第14.6.1节“InnoDB启动配置”和 第14.7.1节“调整InnoDB系统表空间大小”。
所述InnoDB数据字典包括包含用于跟踪对象,如表,索引,和表中的列的元数据的内部系统表。元数据物理上位于InnoDB系统表空间中。由于历史原因,数据字典元数据在一定程度上与存储在InnoDB表元数据文件(.frm文件)中的信息重叠
。
双写缓冲区是一个位于系统表空间中的存储区域,在这个区域中,页面写入数据文件中的适当位置之前,缓冲池中的InnoDB页面被刷新InnoDB。只有在刷新并将页面InnoDB写入双写缓冲区之后,才会
将页面写入其正确的位置。如果在页面写入过程中存在操作系统,存储子系统或
mysqld进程崩溃,InnoDB可以稍后在崩溃恢复期间从双写缓冲区中找到页面的良好副本。
尽管数据总是写入两次,但双写缓冲区不需要两倍的I / O开销或两倍的I / O操作。数据作为一个大的顺序块写入到双写缓冲区本身,只需一次fsync()
调用操作系统。
在大多数情况下,默认情况下会启用doublewrite缓冲区。要禁用双写缓冲区,请设置
innodb_doublewrite为0。
如果系统表空间文件(“ ibdata文件 ”)位于支持原子写入的Fusion-io设备上,则会自动禁用双写缓冲,并将Fusion-io原子写入用于所有数据文件。由于双写缓冲区设置是全局性的,所以对于驻留在非Fusion-io硬件上的数据文件,也会禁用双写缓冲。此功能仅在Fusion-io硬件上受支持,并且仅适用于Linux上的Fusion-io NVMFS。要充分利用此功能,建议使用此innodb_flush_method设置
O_DIRECT。
撤消日志是与单个事务关联的撤消日志记录的集合。撤销日志记录包含有关如何撤消事务对聚集索引 记录的最新更改的信息 。如果另一个事务需要查看原始数据(作为一致读取操作的一部分),则从撤消日志记录中检索未修改的数据。撤销日志存在于 撤消日志段中,该日志段包含在 回滚段中。回滚段位于 系统表空间, 临时表空间和撤消表空间中。有关更多信息,请参阅 第14.7.7节“配置撤消表空间”。有关多版本控制的信息,请参见第14.3节“InnoDB多版本控制”。
InnoDB支持128个回退段,其中32个保留为临时表事务的非重做回滚段。每个更新临时表(不包括只读事务)的事务都被分配了两个回滚段,一个启用了重做的回滚段和一个非重做回滚段。只读事务只分配非重做回滚段,因为只读事务只允许修改临时表。
这留下了96个可用回滚段,每个回滚段支持多达1023个并发数据修改事务,总共限制大约96K个并发数据修改事务。96K限制假定事务不修改临时表。如果所有数据修改事务也修改临时表,则总数限制约为32K个并发数据修改事务。有关为临时表事务保留的回滚段的更多信息,请参见 临时表撤消日志。
该innodb_rollback_segments
选项定义了使用的回退段的数量
InnoDB。
每个文件表的表空间是一个单独的表空间,它是在它自己的数据文件中创建的,而不是在系统表空间中创建的。innodb_file_per_table启用该选项时,将在每个文件表格空间中创建表格
。否则,InnoDB将在系统表空间中创建表。每个每个文件表的表空间由单个.ibd数据文件表示,该数据文件默认在数据库目录中创建。
文件每表的表空间支持DYNAMIC和
COMPRESSED行格式支持诸如用于可变长度数据和表压缩的离页存储之类的功能。有关这些功能以及file-per-table表空间的其他优点的信息,请参见
第14.7.4节“InnoDB每个表文件的表空间”。
InnoDB使用CREATE TABLESPACE语法创建
的共享表空间
。常规表空间可以在MySQL数据目录之外创建,能够保存多个表,并支持所有行格式的表。
表使用或
语法添加到常规表空间
。
CREATE TABLE
tbl_name ... TABLESPACE [=]
tablespace_nameALTER TABLE
tbl_name TABLESPACE [=]
tablespace_name
有关更多信息,请参见第14.7.9节“InnoDB常规表空间”。
撤消表空间包含一个或多个包含撤消日志的文件
。使用的撤消表空间的数量InnoDB由innodb_undo_tablespaces
配置选项定义
。有关更多信息,请参见
部分14.7.7,“配置撤消表空间”。
innodb_undo_tablespaces 已弃用,将在未来版本中删除。
非压缩的用户创建的临时表和磁盘内部临时表是在共享的临时表空间中创建的。的
innodb_temp_data_file_path
配置选项定义了相对路径,名称,规格,和用于临时表空间的数据文件属性。如果未指定值
innodb_temp_data_file_path,则缺省行为是ibtmp1在innodb_data_home_dir目录中创建一个自动扩展数据文件,该
文件的名称
略大于12MB。
压缩的临时表(使用该ROW_FORMAT=COMPRESSED属性创建
的临时表)是在临时文件目录中的文件 - 每表中的表空间中创建的
。
临时表空间在正常关闭或中止初始化时被删除,并在每次启动服务器时重新创建。临时表空间在创建时接收动态生成的空间ID。如果无法创建临时表空间,则启动将被拒绝。如果服务器意外停止,则不会删除临时表空间。在这种情况下,数据库管理员可以手动删除临时表空间或重新启动服务器,该服务器会自动删除并重新创建临时表空间。
临时表空间不能驻留在原始设备上。
INFORMATION_SCHEMA.FILES提供有关InnoDB临时表空间的元数据。发出与此类似的查询来查看临时表空间元数据:
MySQL的> SELECT * FROM INFORMATION_SCHEMA.FILES WHERE TABLESPACE_NAME='innodb_temporary'\G
INFORMATION_SCHEMA.INNODB_TEMP_TABLE_INFO
提供有关在InnoDB实例中当前活动的用户创建的临时表的元数据。有关更多信息,请参见
第14.15.7节“InnoDB INFORMATION_SCHEMA临时表信息表”。
默认情况下,临时表空间数据文件是自动扩展的,并根据需要增加大小以适应磁盘上的临时表。例如,如果某个操作创建了一个大小为20 MB的临时表,则创建时默认大小为12 MB的临时表空间数据文件会扩展以适应该表。当删除临时表时,释放的空间可以重新用于新的临时表,但数据文件保持扩展大小。
在使用大型临时表或广泛使用临时表的环境中,自动扩展临时表空间数据文件可能会变大。长时间运行的使用临时表的查询也可能导致大型数据文件。
要确定临时表空间数据文件是否自动扩展,请检查
innodb_temp_data_file_path
设置:
MySQL的> SELECT @@innodb_temp_data_file_path;
+ ------------------------------ +
| @@ innodb_temp_data_file_path |
+ ------------------------------ +
| ibtmp1:12M:autoextend |
+ ------------------------------ +
要检查临时表空间数据文件的大小,请INFORMATION_SCHEMA.FILES使用类似下面的查询来查询
表:
MySQL的>SELECT FILE_NAME, TABLESPACE_NAME, ENGINE, INITIAL_SIZE, TOTAL_EXTENTS*EXTENT_SIZEAS TotalSizeBytes, DATA_FREE, MAXIMUM_SIZE FROM INFORMATION_SCHEMA.FILESWHERE TABLESPACE_NAME = 'innodb_temporary'\G*************************** 1. row ******************** ******* FILE_NAME:./ibtmp1 TABLESPACE_NAME:innodb_temporary ENGINE:InnoDB INITIAL_SIZE:12582912 TotalSizeBytes:12582912 DATA_FREE:6291456 MAXIMUM_SIZE:NULL
该TotalSizeBytes值报告临时表空间数据文件的当前大小。有关其他字段值的信息,请参见第24.8节“INFORMATION_SCHEMA文件表”。
或者,您可以检查操作系统上的临时表空间数据文件大小。默认情况下,临时表空间数据文件位于由innodb_temp_data_file_path
配置选项定义的目录中
。如果未明确指定此选项的值,ibtmp1则会创建
一个名为临时表空间数据文件,如果未指定,该文件将
innodb_data_home_dir默认为MySQL数据目录。
要回收临时表空间数据文件占用的磁盘空间,可以重新启动MySQL服务器。重新启动服务器将根据定义的属性删除并重新创建临时表空间数据文件
innodb_temp_data_file_path。
为防止临时数据文件变得过大,可以配置该
innodb_temp_data_file_path
选项以指定最大文件大小。例如:
的[mysqld] innodb_temp_data_file_path = ibtmp1:12M:自动扩展:最大:500M
当数据文件达到最大大小时,查询将失败,并显示表已满的错误。配置
innodb_temp_data_file_path
需要重新启动服务器。
或者,您可以配置
default_tmp_storage_engine和
internal_tmp_disk_storage_engine
选项,它们分别定义用于用户创建的和磁盘上的内部临时表的存储引擎。这两个选项InnoDB默认设置为。的
MyISAM存储引擎使用用于每个临时表,当临时表被删除被去除单个文件。
重做日志是在崩溃恢复期间使用的基于磁盘的数据结构,用于纠正由不完整事务写入的数据。在正常操作期间,重做日志将编码请求以更改
InnoDB由SQL语句或低级别API调用产生的表数据。在意外关闭之前没有完成更新数据文件的修改会在初始化期间以及接受连接之前自动重播。有关重做日志在崩溃恢复中的角色的信息,请参见第14.18.2节“InnoDB恢复”。
默认情况下,重做日志在物理上表现为一组文件,名为ib_logfile0和
ib_logfile1。MySQL以循环方式写入重做日志文件。重做日志中的数据按受影响的记录进行编码; 这些数据统称为重做。数据通过重做日志的过程由不断增加的LSN值表示。
有关相关信息,请参阅:
InnoDB与任何其他
ACID兼容的数据库引擎一样,在事务提交之前刷新事务的重做日志。InnoDB
使用组提交
功能将多个此类刷新请求组合在一起,以避免每次提交都有一次刷新。通过组提交,
InnoDB向日志文件发出一次写入操作,以便为大约同时提交的多个用户事务执行提交操作,从而显着提高吞吐量。
有关性能COMMIT和其他事务操作的更多信息
,请参见第8.5.2节“优化InnoDB事务管理”。
要实现大型,繁忙或高度可靠的数据库应用程序,移植来自不同数据库系统的实际代码或调整MySQL性能,理解InnoDB锁定和InnoDB
事务模型非常重要
。
本节讨论与InnoDB锁定有关的几个主题
以及InnoDB
您应该熟悉的事务模型。
第14.5.1节“InnoDB锁定”描述了使用的锁类型
InnoDB。
第14.5.2节“InnoDB事务模型”描述了事务隔离级别和各自使用的锁定策略。它还讨论了使用
autocommit,一致的非锁定读取和锁定读取。
第14.5.3节“在InnoDB中通过不同SQL语句设置的锁”讨论了InnoDB为各种语句设置的特定类型的锁。
第14.5.4节“幻影行”描述了如何
InnoDB使用下一个键锁定来避免幻像行。
第14.5.5节“InnoDB中的死锁”提供了一个死锁例子,讨论了死锁检测和回滚,并提供了最小化和处理死锁的技巧InnoDB。
本节介绍由使用的锁类型
InnoDB。
InnoDB在有两种类型的锁共享(S)锁和
独占(X)锁的情况下实现标准行级锁定
。
如果事务在行上T1保存共享(S)锁r,那么来自某个不同事务T2的对行的锁的请求
r按如下方式处理:
由A请求T2用于
S锁可以立即被授予。其结果是,无论是T1与
T2持有S
的锁r。
通过请求T2一个
X锁不能立即授予。
如果一个事务T1持有一个exclusive(X)锁定行r,则不能立即授予来自某个不同事务的T2
对任一类型锁的请求r。相反,事务T2
必须等待事务T1才能释放行上的锁r。
InnoDB支持多个粒度锁定,允许行锁和表锁共存。例如,诸如
对指定表LOCK TABLES ...
WRITE进行独占锁定(X锁定)的语句
。为了实现多个粒度级别的锁定,InnoDB使用
意向锁。意向锁是表级锁,用于指示事务对表中某一行的事务需要哪种类型的锁(共享或排他)。有两种类型的意向锁:
例如,SELECT ...
LOCK IN SHARE MODE设置一个IS锁,并SELECT ... FOR
UPDATE设置一个IX锁。
意向锁定协议如下:
在一个事务可以获取表中一行上的共享锁之前,它必须先获得一个IS锁或更强的表。
在一个事务可以获得一个表中某一行的排它锁之前,它必须首先获得IX
该表的一个锁。
表级锁定类型的兼容性总结在下面的矩阵中。
X |
IX |
S |
IS |
|
|---|---|---|---|---|
X |
冲突 | 冲突 | 冲突 | 冲突 |
IX |
冲突 | 兼容 | 冲突 | 兼容 |
S |
冲突 | 冲突 | 兼容 | 兼容 |
IS |
冲突 | 兼容 | 兼容 | 兼容 |
如果请求事务与现有的锁定兼容,则授予锁定,但如果它与现有的锁定冲突,则该锁定不会被授予。事务一直等到冲突的现有锁被释放。如果锁定请求与现有的锁冲突并且因为会导致死锁而无法被授予 ,则会发生错误。
意向锁不会阻止除完整表请求之外的任何内容(例如,LOCK
TABLES ... WRITE)。意向锁的主要目的是显示某人正在锁定一行,或者要锁定表中的一行。
意向锁定的交易数据SHOW
ENGINE INNODB STATUS与
InnoDB监视器
输出中的以下内容类似:
TABLE LOCK table`test`.`t` trx id 10080锁定模式IX
记录锁是索引记录上的锁。例如,
SELECT c1 FROM t WHERE c1 = 10 FOR UPDATE;
可以防止从插入,更新或删除行,其中的值的任何其它交易t.c1是
10。
即使没有索引定义表,记录锁始终锁定索引记录。对于这种情况,
InnoDB创建一个隐藏的聚集索引并使用此索引进行记录锁定。请参见
第14.8.2.1节“聚集索引和二级索引”。
记录锁定的事务数据SHOW
ENGINE INNODB STATUS与
InnoDB监视器
输出中的以下内容类似:
记录锁定space id 58 page no 3 n bits 72 index`PRIMARY` table`test`.`t` trx id 10078 lock_mode X锁定rec,但不锁定 记录锁定,堆号2物理记录:n_fields 3; 紧凑格式; 信息位0 0:len 4; 六千八百〇万; asc ;; 1:len 6; 十六进制00000000274f; asc'O ;; 2:len 7; 十六进制b60000019d0110; asc ;;
间隙锁定是索引记录之间的间隙的锁定,或者是第一个或最后一个索引记录之前的间隙锁定。例如,SELECT c1 FROM t WHERE c1 BETWEEN 10 and 20
FOR UPDATE;阻止其他事务15向列中插入值t.c1,而不管列
中是否已有任何此类值,因为范围内所有现有值之间的间隔都是锁定的。
间隔可能跨越单个索引值,多个索引值,甚至是空的。
间隙锁是性能和并发性之间折中的一部分,并且在某些事务隔离级别中使用,而不是在其他级别中使用。
对于使用唯一索引锁定行以搜索唯一行的语句,不需要使用间隙锁定。(这不包括搜索条件仅包含多列唯一索引中的某些列的情况;在这种情况下,会发生间隙锁定)。例如,如果id列具有唯一索引,则以下语句只使用索引记录锁定id值为100 的行,并且其他会话是否在上述间隔中插入行并不重要:
SELECT * FROM child WHERE id = 100;
如果id未被索引或者具有非唯一索引,则该语句确实锁定了前面的差距。
这里也值得注意的是,不同交易可以在差距上保持冲突的锁定。例如,事务A可以在间隔上保存共享间隙锁(间隙S锁),而事务B在同一间隙上保留独占间隙锁(间隙X锁)。允许冲突间隙锁定的原因是,如果从索引中清除记录,则必须合并由不同事务记录保存的间隙锁定。
缺口锁定InnoDB是“ 纯粹抑制性的 ”,这意味着它们只能阻止其他交易进入缺口。它们不会阻止不同的交易在同一个差距上进行差距锁定。因此,间隙X锁具有与间隙S锁相同的效果。
可以显式禁用间隙锁定。如果将事务隔离级别更改为READ COMMITTED或启用
innodb_locks_unsafe_for_binlog
系统变量(现在已弃用),则会发生这种情况
。在这些情况下,对搜索和索引扫描禁用间隙锁定,仅用于外键约束检查和重复键检查。
还有使用READ COMMITTED隔离级别或启用的
其他影响
innodb_locks_unsafe_for_binlog。在MySQL评估WHERE条件之后,释放不匹配行的记录锁。对于
UPDATE语句,InnoDB
执行“ 半连续 ”读取,以便它将最新的提交版本返回给MySQL,以便MySQL可以确定该行是否匹配WHERE
条件UPDATE。
下一个键锁定是索引记录上的记录锁定和索引记录之前的间隙上的间隙锁定的组合。
InnoDB以这样的方式执行行级锁定,即当它搜索或扫描表索引时,它会在遇到的索引记录上设置共享锁或排它锁。因此,行级锁实际上是索引记录锁。索引记录上的下一个键锁定还会影响该索引记录之前的“ 间隙 ”。也就是说,下一个键锁定是索引记录锁定,并在索引记录之前的间隔上加上间隙锁定。如果一个会话R在索引中具有记录中的共享或排它锁定
,则另一个会话不能R在索引顺序中立即在间隙中插入新的索引记录
。
假设索引包含值10,11,13和20.此索引的可能下一个键锁定涵盖以下区间,其中圆括号表示排除区间端点,方括号表示包含端点:
(负无穷,10) (10,11] (11,13] (13,20] (20,正无穷)
对于最后一个时间间隔,下一个键锁定将索引中最大值以上的间隔锁定,并且“ 上游 ” 伪记录的值高于实际在索引中的任何值。上确界不是真实的索引记录,因此,实际上,这个下一个键锁只锁定最大索引值之后的间隔。
默认情况下,InnoDB以
REPEATABLE READ事务隔离级别运行。在这种情况下,InnoDB使用下一个键锁进行搜索和索引扫描,这可以防止幻像行(请参见第14.5.4节“幻像行”)。
下一个键锁定的事务数据SHOW
ENGINE INNODB STATUS与
InnoDB监视器
输出中的以下内容类似:
记录锁定space id 58 page no 3 n bits 72 index`PRIMARY` table`test`.`t` trx id 10080 lock_mode X 记录锁定,堆号1物理记录:n_fields 1; 紧凑格式; 信息位0 0:len 8; 十六进制73757072656d756d; asc supremum ;; 记录锁定,堆号2物理记录:n_fields 3; 紧凑格式; 信息位0 0:len 4; 六千八百〇万; asc ;; 1:len 6; 十六进制00000000274f; asc'O ;; 2:len 7; 十六进制b60000019d0110; asc ;;
插入意向锁定是INSERT在行插入之前通过操作设置的一种间隙锁定
。这个锁定以插入到相同索引间隙中的多个事务不需要等待对方的方式插入的意图,如果它们没有插入间隙中的相同位置。假设有索引记录的值为4和7.单独的事务试图分别插入5和6的值,每个事务都在插入行上获得排它锁之前用插入意向锁来锁定4和7之间的间隔,但不要相互阻塞,因为这些行是非冲突的。
以下示例演示了在获取插入记录的排它锁之前,插入意向锁的事务。这个例子涉及两个客户,A和B.
客户端A创建一个包含两个索引记录(90和102)的表,然后启动一个事务处理,对ID大于100的索引记录进行排它锁定。排它锁包括记录102之前的间隔锁:
mysql>CREATE TABLE child (id int(11) NOT NULL, PRIMARY KEY(id)) ENGINE=InnoDB;mysql>INSERT INTO child (id) values (90),(102);mysql>START TRANSACTION;mysql>SELECT * FROM child WHERE id > 100 FOR UPDATE;+ ----- + | id | + ----- + | 102 | + ----- +
客户B开始交易以将记录插入到间隙中。该事务在等待获得排他锁的同时获取插入意向锁。
mysql>START TRANSACTION;mysql>INSERT INTO child (id) VALUES (101);
插入意图锁定的事务数据SHOW ENGINE INNODB
STATUS与
InnoDB监视器
输出中的以下内容类似
:
记录锁定空间ID 31页面号3 n位72索引表'test`.`child`的`PRIMARY`
trx id 8731 lock_mode X在插入意图等待之前锁定间隙
记录锁,堆号3物理记录:n_fields 3; 紧凑格式; 信息位0
0:len 4; 六角形80000066; asc f ;;
1:len 6; 十六进制000000002215; asc“;;
2:len 7; 六角9000000172011c; asc r ;; ...
一个AUTO-INC锁是通过交易将与表中取得一个特殊的表级锁
AUTO_INCREMENT列。在最简单的情况下,如果一个事务将值插入到表中,则任何其他事务都必须等待对该表执行自己的插入操作,以便第一个事务插入的行接收连续的主键值。
该innodb_autoinc_lock_mode
配置选项控制用于自动增加锁定的算法。它允许您选择如何在可预测的自动递增值序列和插入操作的最大并发之间进行权衡。
有关更多信息,请参见 第14.8.1.5节“InnoDB中的AUTO_INCREMENT处理”。
InnoDB支持SPATIAL
对包含空间列的列进行索引(参见
第11.5.8节“优化空间分析”)。
要处理涉及SPATIAL索引的操作的锁定
,下一个键锁定对支持REPEATABLE
READ或
SERIALIZABLE事务隔离级别不起作用。多维数据中没有绝对的排序概念,因此不清楚哪个是
“ 下一个 ”键。
要为具有SPATIAL索引的表启用支持隔离级别
,请InnoDB
使用谓词锁。甲SPATIAL索引包含最小外接矩形(MBR)值,因此,
InnoDB通过设置用于查询的MBR值的谓词锁强制上的索引一致的读取。其他事务不能插入或修改与查询条件匹配的行。
在InnoDB事务模型中,目标是将多版本数据库的最佳属性
与传统的两阶段锁定相结合。默认情况下,按照Oracle的风格,InnoDB在行级别执行锁定并将查询作为非锁定一致读取运行
。锁定信息
InnoDB存储在空间中,因此不需要锁定升级。通常,允许多个用户锁定InnoDB表中的每一行或任何行的随机子集,而不会导致
InnoDB内存耗尽。
事务隔离是数据库处理的基础之一。隔离是I的首字母缩写 ACID ; 隔离级别是在多个事务进行更改并同时执行查询时,对性能和可靠性之间的平衡,结果的一致性和再现性进行微调的设置。
InnoDB提供由SQL描述的所有四个事务隔离级别:1992标准:
READ UNCOMMITTED,
READ COMMITTED,
REPEATABLE READ,和
SERIALIZABLE。InnoDBis
的默认隔离级别REPEATABLE READ。
用户可以更改单个会话的隔离级别,也可以更改该SET
TRANSACTION语句的所有后续连接。要为所有连接设置服务器的默认隔离级别,请使用
--transaction-isolation命令行或选项文件中的选项。有关隔离级别和级别设置语法的详细信息,请参见
第13.3.6节“SET TRANSACTION语法”。
InnoDB支持使用不同的锁定策略在此描述的每个事务隔离级别
。您可以强制执行与默认REPEATABLE READ级别的高度一致性
,以便对符合ACID要求的关键数据进行操作
。或者,您可以放宽一致性规则,
READ COMMITTED甚至
READ UNCOMMITTED在批量报告等情况下,精确的一致性和可重复的结果不如最小化锁定开销的数量重要。
SERIALIZABLE执行更严格的规则REPEATABLE
READ,而且主要用于特殊情况下,如XA事务和解决并发和死锁问题
。
以下列表描述了MySQL如何支持不同的事务级别。该列表从最常用的级别到最少使用的级别。
这是默认的隔离级别
InnoDB。
在同一事务中的一致读取读取第一次读取建立的
快照。这意味着,如果您SELECT
在同一个事务中发出多个纯(非锁定)语句,这些
SELECT语句在彼此之间也是一致的。请参见
第14.5.2.3节“一致性非锁定读取”。
对于锁定读取
(SELECT使用FOR
UPDATE或LOCK IN SHARE MODE),
UPDATE和
DELETE语句,锁定取决于语句是使用具有唯一搜索条件的唯一索引还是范围类型搜索条件。
对于具有唯一搜索条件的唯一索引,
InnoDB仅锁定找到的索引记录,而不是锁定
之前的间隔。
对于其他搜索条件,InnoDB
使用间隙锁或
下一个键锁
来锁定扫描的索引范围,
以阻止其他会话插入到范围所覆盖的间隙中。有关间隙锁和下一个键锁的信息,请参见
第14.5.1节“InnoDB锁定”。
即使在同一个事务中,每次一致的读取都会设置并读取其自己的新快照。有关一致读取的信息,请参见 第14.5.2.3节“一致性非锁定读取”。
对于锁定读取(SELECT
使用FOR UPDATE或LOCK IN SHARE
MODE),UPDATE
语句和DELETE
语句,InnoDB只锁定索引记录,而不锁定它们之前的间隔,从而允许在锁定记录旁边自由插入新记录。间隙锁定仅用于外键约束检查和重复键检查。
由于禁用了间隙锁定,所以可能会出现幻影问题,因为其他会话可以将新行插入到间隙中。有关幻影的信息,请参见 第14.5.4节“幻影行”。
如果您使用READ COMMITTED,则
必须使用基于行的二进制日志记录。
使用READ COMMITTED有其他影响:
考虑下面的例子,从这个表开始:
CREATE TABLE t(INT NOT NULL,b INT)ENGINE = InnoDB; 插入t值(1,2),(2,3),(3,2),(4,3),(5,2); 承诺;
在这种情况下,该表没有索引,因此搜索和索引扫描使用隐藏聚簇索引进行记录锁定(请参见第14.8.2.1节“聚簇索引”和“二级索引”)而不是索引列。
假设一个会话UPDATE使用这些语句执行
:
#会话A 开始交易; UPDATE t SET b = 5 WHERE b = 3;
假设第二个会话
UPDATE通过在第一个会话之后执行这个语句来执行:
#会话B UPDATE t SET b = 4 WHERE b = 2;
由于InnoDB每个执行
UPDATE时,它首先获取用于它读取,并且然后确定是否要修改它的每一行的排他锁。如果
InnoDB不修改该行,则释放该锁。否则,
InnoDB保留锁直到交易结束。这会影响事务处理,如下所示。
当使用默认REPEATABLE READ
隔离级别时,第
UPDATE一个在它读取的每一行上获取一个x锁,并且不释放它们中的任何一个:
X锁(1,2); 保留x锁 X锁(2,3); 更新(2,3)至(2,5); 保留x锁 X锁(3,2); 保留x锁 X锁(4,3); 更新(4,3)至(4,5); 保留x锁 X锁(5,2); 保留x锁
第二次UPDATE尝试获取任何锁(因为第一次更新保留了所有行上的锁)就立即阻塞,直到第一次UPDATE提交或回滚时才会继续:
X锁(1,2); 阻止并等待第一个UPDATE提交或回滚
如果READ COMMITTED使用它,第UPDATE一个会在它读取的每一行上获取一个x-lock,并为那些未修改的行释放它们:
X锁(1,2); 解锁(1,2) X锁(2,3); 更新(2,3)至(2,5); 保留x锁 X锁(3,2); 解锁(3,2) X锁(4,3); 更新(4,3)至(4,5); 保留x锁 X锁(5,2); 解锁(5,2)
对于第二种情况UPDATE,
InnoDB执行
“ 半连续 ”读取,将其读取的每一行的最新提交版本返回给MySQL,以便MySQL可以确定该行是否与以下WHERE条件
匹配
UPDATE:
X锁(1,2); 更新(1,2)至(1,4); 保留x锁 X锁(2,3); 解锁(2,3) X锁(3,2); 更新(3,2)至(3,4); 保留x锁 X锁(4,3); 解锁(4,3) X锁(5,2); 更新(5,2)至(5,4); 保留x锁
但是,如果WHERE条件包含索引列并InnoDB使用该索引,则在获取和保留记录锁时仅考虑索引列。在下面的例子中,第
UPDATE一个在b = 2的每一行上获取并保留一个x锁。UPDATE当它尝试获取相同记录上的x锁时,第二个
块会使用在列b上定义的索引。
CREATE TABLE t(INT NOT NULL,b INT,c INT,INDEX(b))ENGINE = InnoDB; 插入t值(1,2,3),(2,2,4); 承诺; #会话A 开始交易; UPDATE t SET b = 3 WHERE b = 2 AND c = 3; #会话B UPDATE t SET b = 4 WHERE b = 2 AND c = 4;
使用READ COMMITTED
隔离级别的效果与启用不建议的
innodb_locks_unsafe_for_binlog
配置选项相同,但有以下例外:
启用
innodb_locks_unsafe_for_binlog
是一个全局设置,会影响所有会话,而隔离级别可以全局设置为所有会话,也可以单独设置每个会话。
innodb_locks_unsafe_for_binlog
只能在服务器启动时设置,而隔离级别可以在启动时设置或在运行时更改。
READ COMMITTED因此提供更好,更灵活的控制
innodb_locks_unsafe_for_binlog。
SELECT语句以非锁定方式执行,但可能会使用一个可能的早期版本的行。因此,使用这种隔离级别,这样的读取不一致。这也被称为
脏读。否则,这个隔离级别就像
READ COMMITTED。
这个级别就像REPEATABLE
READ,但InnoDB隐式地将所有简单SELECT
语句转换为SELECT
... LOCK IN SHARE MODEif
autocommit被禁用。如果
autocommit启用,则
SELECT是它自己的事务。因此,它被认为是只读的,并且如果作为一致(非锁定)读取执行,则可以被序列化,并且不需要阻塞其他事务。(SELECT如果其他事务修改了选定的行,强制平原
阻止,请禁用
autocommit。)
在中InnoDB,所有的用户活动都发生在一个事务中。如果autocommit启用了模式,则每个SQL语句都会自行形成一个事务。默认情况下,MySQL在autocommit
启用时为每个新连接启动会话,所以如果该语句没有返回错误,则MySQL会在每个SQL语句后执行提交。如果语句返回错误,则提交或回滚行为取决于错误。请参见
第14.21.4节“InnoDB错误处理”。
具有会话autocommit
启用可以通过显式启动它执行多语句事务
START
TRANSACTION或
BEGIN
语句,并用它结束
COMMIT或
ROLLBACK
声明。请参见第13.3.1节“START TRANSACTION,COMMIT和ROLLBACK语法”。
如果autocommit模式在会话中被禁用SET autocommit = 0,则会话始终打开一个事务。A
COMMIT或
ROLLBACK
语句结束当前交易并开始新交易。
如果一个autocommit没有明确提交最终事务的禁用会话
结束,MySQL会回滚该事务。
一些语句隐式地结束了一个事务,就好像你COMMIT在执行语句之前完成了一样。有关详细信息,请参见第13.3.3节“导致隐式提交的语句”。
这COMMIT意味着在当前交易中所做的更改将永久化,并对其他会话可见。一个
ROLLBACK
声明,而另一方面,取消当前事务中的所有修改。双方
COMMIT并
ROLLBACK
释放所有InnoDB当前事务期间设置的锁。
默认情况下,连接到MySQL服务器开始与 自动提交模式启用,当你执行它自动提交每个SQL语句。如果您对其他数据库系统有经验,那么这种操作模式可能并不熟悉,在这种模式下,发布一系列DML语句并提交它们或将它们一起回滚是标准做法 。
要使用多语句
事务,开关自动提交了与SQL语句SET autocommit
= 0,并结束与每一笔交易
COMMIT或
ROLLBACK为合适。要使自动提交功能开启,请START
TRANSACTION使用COMMIT或
开始每个事务并以其结束
ROLLBACK。以下示例显示了两个事务。第一个承诺; 第二个回滚。
外壳> mysql test
MySQL的>CREATE TABLE customer (a INT, b CHAR (20), INDEX (a));查询OK,0行受影响(0.00秒) mysql>-- Do a transaction with autocommit turned on.mysql>START TRANSACTION;查询OK,0行受影响(0.00秒) MySQL的>INSERT INTO customer VALUES (10, 'Heikki');查询OK,1行受影响(0.00秒) MySQL的>COMMIT;查询OK,0行受影响(0.00秒) mysql>-- Do another transaction with autocommit turned off.mysql>SET autocommit=0;查询OK,0行受影响(0.00秒) MySQL的>INSERT INTO customer VALUES (15, 'John');查询OK,1行受影响(0.00秒) MySQL的>INSERT INTO customer VALUES (20, 'Paul');查询OK,1行受影响(0.00秒) MySQL的>DELETE FROM customer WHERE b = 'Heikki';查询OK,1行受影响(0.00秒) mysql>-- Now we undo those last 2 inserts and the delete.mysql>ROLLBACK;查询OK,0行受影响(0.00秒) MySQL的>SELECT * FROM customer;+ ------ + -------- + | a | b | + ------ + -------- + | 10 | Heikki | + ------ + -------- + 一排(0.00秒) MySQL的>
在诸如PHP,Perl DBI,JDBC,ODBC或MySQL的标准C调用接口之类的API中,您可以将事务控制语句(例如COMMIT任何其他SQL语句(如SELECTor))
作为字符串发送到MySQL服务器INSERT。一些API还提供单独的特殊事务提交和回滚函数或方法。
甲一致的读取
该装置InnoDB使用多版本呈现给一个查询数据库的快照在一个时间点。该查询可以查看在该时间点之前提交的事务所做的更改,以及以后或未提交的事务所做的更改。此规则的例外是该查询查看同一事务中较早的语句所做的更改。此异常会导致以下异常:如果更新表中的某些行,请执行下列操作:
SELECT看到最新版本的更新行,但它也可能会看到任何行的旧版本。如果其他会话同时更新同一个表,异常意味着您可能会看到该表处于数据库中从未存在的状态。
如果事务
隔离级别是
REPEATABLE READ(缺省级别),则同一事务中的所有一致读取将读取该事务中第一次读取所创建的快照。您可以通过提交当前事务并在发出新查询之后为您的查询获得更新鲜的快照。
通过READ COMMITTED隔离级别,事务中的每次一致读取都会设置并读取其自己的新快照。
一致的读取是InnoDB进程
SELECT声明
READ COMMITTED和
REPEATABLE READ隔离级别的默认模式
。一致的读取不会在它访问的表上设置任何锁,因此其他会话可以自由修改这些表,同时在表上执行一致的读取。
假设您正在运行默认的
REPEATABLE READ隔离级别。当您发出一致的读取(即普通
SELECT语句)时,
InnoDB会为您的事务提供一个根据您的查询查看数据库的时间点。如果另一个事务删除了一行并在分配了时间点后提交,则不会看到该行已被删除。插入和更新的处理方式相似。
数据库状态的快照适用
SELECT于事务内的语句,不一定适用于
DML语句。如果您插入或修改某些行,然后提交该交易中,
DELETE或
UPDATE从其他并发发出声明REPEATABLE READ
的交易可能会影响到刚刚犯行,即使会议无法对它们进行查询。如果事务更新或删除由不同事务提交的行,则这些更改对当前事务变得可见。例如,您可能会遇到如下情况:
SELECT COUNT(c1)FROM t1 WHERE c1 ='xyz'; - 返回0:没有行匹配。 DELETE FROM t1 WHERE c1 ='xyz'; - 删除其他事务最近提交的几行。 SELECT COUNT(c2)FROM t1 WHERE c2 ='abc'; - 返回0:没有行匹配。 UPDATE t1 SET c2 ='cba'WHERE c2 ='abc'; - 影响10行:另一个txn只提交了10行'abc'值。 SELECT COUNT(c2)FROM t1 WHERE c2 ='cba'; - 返回10:这个txn现在可以看到它刚刚更新的行。
你可以通过提交你的交易来完成你的时间点,然后再做另一个SELECT或者
START TRANSACTION WITH
CONSISTENT SNAPSHOT。
这称为多版本并发控制。
在下面的例子中,只有当B提交了插入并且A已经提交时,会话A才看到由B插入的行,以便时间点超过B的提交。
会议A会议B
SET autocommit = 0; SET autocommit = 0;
时间
| SELECT * FROM t;
| 空集
| 插入t值(1,2);
|
v SELECT * FROM t;
空集
承诺;
SELECT * FROM t;
空集
承诺;
SELECT * FROM t;
---------------------
| 1 | 2 |
---------------------
如果要查看数据库的“ 最新 ”状态,请使用READ
COMMITTED隔离级别或
锁定读取:
SELECT * FROM t FOR SHARE;
通过READ COMMITTED隔离级别,事务中的每次一致读取都会设置并读取其自己的新快照。使用时LOCK IN SHARE
MODE,会发生锁定读取:A
SELECT阻塞,直到包含最新行的事务结束(请参见
第14.5.2.4节“锁定读取”)。
一致的读取不适用于某些DDL语句:
一致的读取无法完成DROP
TABLE,因为MySQL不能使用已经被删除并InnoDB破坏表格的表格。
一致的读取不会结束
ALTER TABLE,因为该语句创建原始表的临时副本,并在构建临时副本时删除原始表。在事务中重新发布一致的读取时,新表中的行不可见,因为在执行事务快照时,这些行不存在。在这种情况下,事务返回错误:
ER_TABLE_DEF_CHANGED,
“ 表定义已更改,请重试事务 ”。
读取的类型因条件(例如INSERT INTO ...
SELECT,)中的选择而不同
UPDATE
... (SELECT),并且
CREATE TABLE ...
SELECT不指定FOR
UPDATE或LOCK IN SHARE MODE:
默认情况下,InnoDB使用更强的锁定,并且该SELECT部分的作用就像
READ COMMITTED,即使在同一事务中,每次一致的读取都会设置并读取其自己的新快照。
要在这种情况下,读一致性,使
innodb_locks_unsafe_for_binlog
选项和事务的隔离级别设置为
READ UNCOMMITTED,
READ COMMITTED或
REPEATABLE READ(也就是比其他任何东西
SERIALIZABLE)。在这种情况下,从所选表格读取的行上不设置锁定。
如果您查询数据,然后在同一个事务中插入或更新相关数据,则常规SELECT
语句不会提供足够的保护。其他事务可以更新或删除刚才查询的相同行。
InnoDB支持两种提供额外安全性的
锁定读取:
在读取的任何行上设置共享模式锁定。其他会话可以读取行,但在您的事务提交之前无法修改它们。如果这些行中的任何一行已被另一个尚未提交的事务更改,那么您的查询将一直等到该事务结束,然后使用最新值。
对于搜索遇到的索引记录,锁定行和任何关联的索引条目,就像UPDATE为这些行发布
语句一样。其他事务被阻止更新这些行,不执行SELECT ... LOCK IN SHARE MODE或以某些事务隔离级别读取数据。一致的读取忽略读取视图中存在的记录上设置的任何锁定。(记录的旧版本不能被锁定;它们通过在记录的内存副本上应用撤消日志来重建
。)
这些子句在处理树形结构或图形结构化数据时非常有用,无论是在单个表中还是在多个表中拆分。您可以将边或树枝从一处移到另一处,同时保留返回并更改这些 “ 指针 ”值的权利。
当事务被提交或回滚时,
所有由设置LOCK IN SHARE MODE和
FOR UPDATE查询设置的锁都会被释放。
SELECT FOR
UPDATE仅在自动提交被禁用时(START
TRANSACTION或者通过设置autocommit为0 开始事务
或通过设置
为0来
锁定行以进行更新)。如果启用自动提交,则与规范匹配的行不会被锁定。
假设你想在表中插入一个新行
child,并确保子行在表中有一个父行parent。您的应用程序代码可以确保贯穿这一系列操作的参照完整性。
首先,使用一致的读取来查询表
PARENT并验证父行是否存在。你能安全地将子行插入表中
CHILD吗?不,因为其他会话可能会在您SELECT和您之间的那一刻删除父行
INSERT,而您没有意识到它。
为避免此潜在问题,请执行以下
SELECT操作LOCK IN
SHARE MODE:
SELECT * FROM parent WHERE NAME ='Jones'锁定共享模式;
在之后LOCK IN SHARE MODE的查询返回父'Jones',你可以放心地将孩子记录添加到CHILD表并提交事务。任何尝试获取PARENT表中适用行的排它锁的事务都会
等待,直到完成为止,也就是说,直到所有表中的数据处于一致状态。
又如,考虑表中的整数计数器字段CHILD_CODES,用于为添加到表的每个子项分配唯一标识符
CHILD。不要使用一致性读取或共享模式读取读取计数器的当前值,因为数据库的两个用户可能会看到计数器的相同值,并且如果两个事务尝试添加行,则会出现重复键错误CHILD表格中的标识符相同。
在这里,LOCK IN SHARE MODE这不是一个好的解决方案,因为如果两个用户同时读取计数器,当它尝试更新计数器时,至少有一个用户死锁。
要实现读取和递增计数器,首先使用计数器对计数器进行锁定读取FOR
UPDATE,然后递增计数器。例如:
SELECT counter_field FROM child_codes FOR UPDATE; UPDATE child_codes SET counter_field = counter_field + 1;
A SELECT ... FOR
UPDATE读取最新的可用数据,在其读取的每一行上设置独占锁。因此,它设置了搜索SQL UPDATE
将在行上设置的相同锁。
前面的描述仅仅是一个如何SELECT ... FOR
UPDATE工作的例子
。在MySQL中,生成唯一标识符的具体任务实际上可以使用对表的单一访问来完成:
UPDATE child_codes SET counter_field = LAST_INSERT_ID(counter_field + 1); SELECT LAST_INSERT_ID();
该SELECT语句仅检索标识符信息(特定于当前连接)。它不访问任何表。
一个锁定读,一个
UPDATE或
DELETE一般设置纪录是在SQL语句的处理扫描每个索引记录锁定。WHERE在声明中是否存在会排除该行的条件并不重要
。InnoDB不记得确切的WHERE情况,但只知道扫描了哪些索引范围。这些锁通常是下
一个键锁,它也会在记录之前立即阻止插入“ 间隙 ”中。但是,
可以显式禁用间隙锁定,这会导致不使用下一个锁定键。有关更多信息,请参阅
第14.5.1节“InnoDB锁定”。事务隔离级别还可以影响设置了哪些锁; 请参见
第14.5.2.1节“事务隔离级别”。
如果在搜索中使用辅助索引,并且要设置的索引记录锁是独占的,则InnoDB还会检索相应的聚集索引记录并在其上设置锁。
第14.5.1节“InnoDB锁定” 介绍了共享锁和独占锁之间的区别 。
如果您没有适合您的语句的索引,并且MySQL必须扫描整个表以处理语句,则表的每一行都会被锁定,从而阻止其他用户的所有插入到表中。创建好的索引非常重要,以便您的查询不会不必要地扫描多行。
对于SELECT ... FOR
UPDATEor SELECT
... LOCK IN SHARE MODE,锁定是为扫描行获取的,并且对于不符合结果集条件的行(例如,如果它们不符合WHERE条款中给出的条件),将被释放。但是,在某些情况下,行可能不会立即解锁,因为在执行查询期间,结果行与其原始源之间的关系会丢失。例如,在一个
UNION,从表中扫描(和锁定)的行可能会在评估之前插入临时表中,以确定它们是否符合结果集。在这种情况下,临时表中的行与原始表中的行之间的关系会丢失,并且后面的行在查询执行结束之前不会解锁。
InnoDB 如下设置特定类型的锁。
SELECT ...
FROM是一致的读取,读取数据库的快照并设置不锁定,除非事务隔离级别设置为
SERIALIZABLE。对于
SERIALIZABLE级别,搜索会在遇到的索引记录上设置共享的下一个键锁。但是,对于使用唯一索引锁定行来搜索唯一行的语句,只需要索引记录锁定。
SELECT ... FROM ...
LOCK IN SHARE MODE在搜索遇到的所有索引记录上设置共享的下一个键锁定。但是,对于使用唯一索引锁定行来搜索唯一行的语句,只需要索引记录锁定。
SELECT ... FROM ...
FOR UPDATE在搜索遇到的每个记录上设置唯一的下一个键锁定。但是,对于使用唯一索引锁定行来搜索唯一行的语句,只需要索引记录锁定。
对于搜索遇到的索引记录,
SELECT ... FROM ...
FOR UPDATE阻止其他会话执行
SELECT ... FROM ...
LOCK IN SHARE MODE或读取某些事务隔离级别。一致的读取忽略读取视图中存在的记录上设置的任何锁定。
UPDATE ... WHERE
...在搜索遇到的每个记录上设置唯一的下一个键锁定。但是,对于使用唯一索引锁定行来搜索唯一行的语句,只需要索引记录锁定。
当UPDATE修改一个聚集索引记录,隐含的锁被采取对受影响的第二个索引记录。UPDATE在插入新的二级索引记录之前执行重复检查扫描时以及插入新的二级索引记录时,该
操作还会对受影响的二级索引记录执行共享锁定。
DELETE FROM ... WHERE
...在搜索遇到的每个记录上设置唯一的下一个键锁定。但是,对于使用唯一索引锁定行来搜索唯一行的语句,只需要索引记录锁定。
INSERT在插入的行上设置独占锁。该锁是一个索引记录锁,而不是下一个键锁(即没有间隙锁),并且不会阻止其他会话插入到插入行之前的间隙中。
在插入行之前,设置一种称为插入意图间隙锁的间隙锁。这个锁定以插入到相同索引间隙中的多个事务不需要等待对方的方式插入的意图,如果它们没有插入间隙中的相同位置。假设有索引记录的值为4和7.尝试插入5和6值的单独事务每个在插入行上获得排它锁之前用插入意向锁锁定4和7之间的间隔,但不要因为行不冲突而彼此阻塞。
如果发生重复键错误,则会设置重复索引记录上的共享锁。如果另一个会话已具有排他锁,则如果有多个会话尝试插入同一行,则此共享锁的使用可能导致死锁。如果另一个会话删除该行,则会发生这种情况。假设InnoDB表格
t1具有以下结构:
CREATE TABLE t1(INT,PRIMARY KEY(i))ENGINE = InnoDB;
现在假设三个会话按顺序执行以下操作:
第一部分:
开始交易; INSERT INTO t1 VALUES(1);
会议2:
开始交易; INSERT INTO t1 VALUES(1);
第三场:
开始交易; INSERT INTO t1 VALUES(1);
第一部分:
ROLLBACK;
会话1的第一个操作获取该行的排它锁。会话2和3的操作都会导致重复键错误,并且它们都会为该行请求共享锁。当会话1回滚时,它将释放对该行的排它锁,并为会话2和3授予排队的共享锁请求。此时,会话2和3发生死锁:因为另一方持有共享锁,所以都不能获得该行的排它锁。
如果表中已经包含具有键值1的行并且三个会话按顺序执行以下操作,则会出现类似的情况:
第一部分:
开始交易; DELETE FROM t1 WHERE i = 1;
会议2:
开始交易; INSERT INTO t1 VALUES(1);
第三场:
开始交易; INSERT INTO t1 VALUES(1);
第一部分:
承诺;
会话1的第一个操作获取该行的排它锁。会话2和3的操作都会导致重复键错误,并且它们都会为该行请求共享锁。当会话1提交时,它将释放对该行的排它锁,并为会话2和3授予排队的共享锁请求。此时,会话2和3发生死锁:由于另一方持有共享锁,因此无法获得该行的排它锁。
INSERT
... ON DUPLICATE KEY UPDATE不同之处在于
INSERT当发生重复密钥错误时,在要更新的行上放置排他锁而不是共享锁。对重复的主键值采取独占索引记录锁定。独占的下一个键锁定用于重复的唯一键值。
INSERT INTO T SELECT ... FROM S WHERE ...
在插入的每一行上设置独占索引记录锁(无间隙锁)T。如果事务隔离级别为READ
COMMITTED或
innodb_locks_unsafe_for_binlog
已启用且事务隔离级别不是
SERIALIZABLE,
InnoDB那么S作为一致性读取进行搜索
(不锁定)。否则,InnoDB在行上设置共享的下一个键锁S。
InnoDB必须在后一种情况下设置锁定:在从备份中前滚恢复时,每个SQL语句必须以与原来完成的方式完全相同的方式执行。
CREATE TABLE ...
SELECT ...执行
SELECT与共享的下一个键锁定或作为一致的读取,如
INSERT ...
SELECT。
当SELECT在构建中使用
REPLACE INTO t SELECT ... FROM s WHERE ...
或UPDATE t ... WHERE col IN (SELECT ... FROM s
...),InnoDB集共享来自表中的行的下键锁s。
在初始化AUTO_INCREMENT表中先前指定的
列的同时,在
InnoDB与该AUTO_INCREMENT列关联的索引的末尾设置排它锁
。在访问自动增量计数器时,InnoDB使用特定的AUTO-INC表锁定模式,其中锁只持续到当前SQL语句的末尾,而不是整个事务的末尾。其他会话在AUTO-INC
表锁被保持时不能插入到表中; 请参见
第14.5.2节“InnoDB事务模型”。
InnoDB在AUTO_INCREMENT不设置任何锁的情况下获取先前初始化的列的值。
如果FOREIGN KEY在表上定义了一个约束,那么需要检查约束条件的任何插入,更新或删除都会在它检查约束的记录上设置共享记录级锁。
InnoDB还会在约束失败的情况下设置这些锁。
LOCK TABLES设置表锁,但它是InnoDB设置这些锁的图层上面的较高MySQL层
。
InnoDB如果
innodb_table_locks = 1(默认)以及
autocommit = 0上面的MySQL层InnoDB知道行级锁,就知道表锁。
否则,InnoDB在涉及这种表锁的情况下,自动死锁检测无法检测到死锁。另外,因为在这种情况下,较高的MySQL层不知道行级别锁定,所以可以在另一个会话当前具有行级别锁定的表上获得表锁定。但是,这不会危及事务完整性,如
第14.5.5.2节“死锁检测和回滚”中所述。另请参见
第14.8.1.7节“InnoDB表的限制”。
当相同的查询在不同时间产生不同组的行时,
所谓的幻影问题发生在事务中。例如,如果a
SELECT被执行了两次,但第二次返回的是第一次未返回的行,则该行是“ 幻影 ”行。
假设表的id列上有一个索引,child并且您希望读取并锁定标识符值大于100的表中的所有行,并打算稍后更新所选行中的某一列:
SELECT * FROM child WHERE id> 100 FOR UPDATE;
查询从id大于100 的第一条记录开始扫描索引
。让该表包含id值为90和102的行。如果在扫描范围内的索引记录上设置的锁不锁定在间隙中进行的插入在这种情况下,90和102之间的差距),另一个会话可以id在101 的表中插入一个新行
。如果要在同SELECT一个事务中执行
相同的事务,则会看到一个id101 行的新行(一个
“ 幻影 ”)在查询返回的结果集中。如果我们将一组行视为一个数据项,那么新的幻像子将违反事务应该能够运行的事务的隔离原则,以便在事务处理期间它所读取的数据不会改变。
为了防止幻像,InnoDB使用称为下一个键锁定的算法,该算法结合了索引行锁定和间隙锁定。
InnoDB以这样的方式执行行级锁定,即当它搜索或扫描表索引时,它会在遇到的索引记录上设置共享锁或排它锁。因此,行级锁实际上是索引记录锁。另外,索引记录上的下一个键锁也会影响该索引记录之前的
“ 间隙 ”。也就是说,下一个键锁定是索引记录锁定,并在索引记录之前的间隔上加上间隙锁定。如果一个会话有记录的共享或排他锁R在索引中,另一个会话不能R在索引顺序中立即在间隙中插入新的索引记录
。
当InnoDB扫描索引,它也可以锁定在指数的最后一个记录之后的间隙。在前面的例子中,就发生了这种情况:为了防止在表中插入
id大于100的任何数据,设置
InnoDB的锁在id值102之后的间隙中包含一个锁
。
您可以使用下一个键锁定在您的应用程序中实现唯一性检查:如果您以共享模式读取数据,并且没有看到要插入的行的重复项,那么您可以安全地插入行并知道在读取过程中设置在行的后继键上的下一个键锁可以防止任何人同时为行插入副本。因此,下一个键锁定使您能够“ 锁定 ”表中不存在的东西。
可以禁用间隙锁定,如 第14.5.1节“InnoDB锁定”中所述。这可能会导致幻影问题,因为当禁用间隙锁定时,其他会话可以将新行插入到间隙中。
死锁是由于每个事务持有另一个需要的锁而导致不同事务无法继续的情况。因为两个事务都在等待资源变为可用,所以既不释放它拥有的锁。
当事务锁定多个表中的行时(通过诸如UPDATE或的
语句SELECT ... FOR
UPDATE),可能会发生死锁
,但顺序相反。当这些语句锁定索引记录和间隔的范围时,也会发生死锁,每个事务由于计时问题而获取一些锁而不是其他锁。有关死锁示例,请参见
第14.5.5.1节“InnoDB死锁示例”。
为了减少死锁的可能性,使用事务而不是LOCK TABLES语句; 保持插入或更新数据的事务足够小以至于不能长时间保持打开状态; 当不同的事务更新多个表或大范围的行时,请SELECT ... FOR
UPDATE在每个事务中使用相同的操作顺序(例如
); 在SELECT ...
FOR UPDATE和
UPDATE ... WHERE
语句中使用的列上创建索引。死锁的可能性不受隔离级别的影响,因为隔离级别改变了读操作的行为,而死锁因为写操作而发生。有关避免和从死锁状态恢复的更多信息,请参阅
第14.5.5.3节“如何最小化和处理死锁”。
当启用死锁检测(默认)并发生死锁时,InnoDB检测条件并回滚其中一个事务(受害者)。如果使用innodb_deadlock_detect
配置选项禁用死锁检测
,则InnoDB依赖该
innodb_lock_wait_timeout设置来回滚死锁情况下的事务。因此,即使您的应用程序逻辑正确,您仍然必须处理必须重试事务的情况。要查看InnoDB用户事务中的最后一个死锁,请使用该
SHOW ENGINE INNODB
STATUS命令。如果频繁死锁突出显示事务结构或应用程序错误处理的问题,请使用
innodb_print_all_deadlocks
设置启用将有关所有死锁的信息打印到
mysqld错误日志中。有关死锁如何自动检测和处理的更多信息,请参见
第14.5.5.2节“死锁检测和回滚”。
以下示例说明了锁请求会导致死锁时如何发生错误。这个例子涉及两个客户,A和B.
首先,客户端A创建一个包含一行的表,然后开始一个事务。在事务中,A通过S在共享模式中选择它来获得
行上的锁定:
MySQL的>CREATE TABLE t (i INT) ENGINE = InnoDB;查询OK,0行受影响(1.07秒) MySQL的>INSERT INTO t (i) VALUES(1);查询OK,1行受影响(0.09秒) MySQL的>START TRANSACTION;查询OK,0行受影响(0.00秒) MySQL的>SELECT * FROM t WHERE i = 1 LOCK IN SHARE MODE;+ ------ + | 我| + ------ + | 1 | + ------ +
接下来,客户端B开始一个事务并尝试从表中删除该行:
MySQL的>START TRANSACTION;查询OK,0行受影响(0.00秒) MySQL的>DELETE FROM t WHERE i = 1;
删除操作需要X
锁定。该锁不能被授予,因为它与S客户端A持有的锁不兼容,所以该请求会进入行和客户端B块的锁请求队列。
最后,客户端A也尝试从表中删除该行:
MySQL的> DELETE FROM t WHERE i = 1;
错误1213(40001):尝试获取锁定时发现死锁;
尝试重新启动事务
死锁发生在这里,因为客户端A需要一个
X锁来删除该行。但是,该锁定请求不能被授予,因为客户端B已经有一个X锁定请求并且正在等待客户端A释放其S
锁定。由于B事先请求锁定,因此SA持有的锁也不能升级X为X锁。因此,InnoDB为其中一个客户端生成错误并释放其锁。客户返回这个错误:
错误1213(40001):尝试获取锁定时发现死锁; 尝试重新启动事务
此时,可以授予其他客户端的锁定请求,并从表中删除该行。
当启用死锁检测(默认)时,会
InnoDB自动检测事务
死锁并回退一个或多个事务来打破死锁。
InnoDB尝试选择小事务回滚,其中事务的大小由插入,更新或删除的行数确定。
InnoDB知道表锁如果
innodb_table_locks = 1(默认)
autocommit = 0,并且上层的MySQL层知道行级锁。否则,
InnoDB无法检测由MySQL LOCK TABLES
语句设置的表锁或由InnoDB涉及的其他存储引擎设置的锁的死锁
。通过设置innodb_lock_wait_timeout系统变量的值来解决这些情况
。
在InnoDB执行事务的完整回滚时,释放由事务设置的所有锁。但是,如果只有一条SQL语句由于错误而回滚,则该语句设置的某些锁可能会被保留。发生这种情况是因为InnoDB
存储行格式的锁定的格式使得它无法知道哪个锁由哪个语句设置。
如果SELECT在事务中调用存储的函数,并且函数中的语句失败,那么该语句会回滚。而且,如果
ROLLBACK在此之后执行,则整个事务回滚。
如果LATEST DETECTED DEADLOCK第
InnoDB监视器输出包括一条消息指出,“ 过深或长时间的搜寻锁表WAITS-FOR图中,我们将回滚下面的事务, ”这表明交易的所述等待名单上的人数已经达到了限制为200.超过200个事务的等待列表被视为死锁,并且试图检查等待列表的事务将被回滚。如果锁定线程必须查看等待列表上的事务拥有的超过1,000,000个锁,则也会发生同样的错误。
有关组织数据库操作以避免死锁的技术,请参见第14.5.5节“InnoDB中的死锁”。
在高并发系统上,当大量线程等待相同的锁时,死锁检测会导致速度下降。有时候,innodb_lock_wait_timeout
当死锁发生时,禁用死锁检测并依赖事务回滚的设置可能更有效
。使用innodb_deadlock_detect
配置选项可以禁用死锁检测
。
本节基于第14.5.5.2节“死锁检测和回滚”中关于死锁的概念信息。它解释了如何组织数据库操作以最大限度地减少死锁以及应用程序中所需的后续错误处理。
死锁是交易数据库中的一个典型问题,但它们并不危险,除非它们频繁发生,根本无法运行某些事务。通常,您必须编写应用程序,以便它们随时准备重新发出一个事务,如果它由于死锁而回滚。
InnoDB使用自动行级锁定。即使在插入或删除单行的事务中,也可能会出现死锁。那是因为这些行动并非真正的“ 原子 ”。他们自动在插入或删除的行的索引记录(可能有几个)上设置锁定。
您可以通过以下技术来应对死锁并减少它们发生的可能性:
在任何时候,发出该
SHOW ENGINE
INNODB STATUS命令以确定最近发生的死锁的原因。这可以帮助您调整应用程序以避免死锁。
如果经常出现死锁警告,请通过启用innodb_print_all_deadlocks
配置选项收集更多的调试信息
。关于每个死锁的信息,不仅仅是最新的,记录在MySQL
错误日志中。完成调试后禁用此选项。
如果事务由于死锁而失败,请始终准备重新发出事务。僵局并不危险。再试一次。
保持交易持续时间较短,以减少冲突。
在进行一系列相关更改后立即提交事务,以减少冲突。特别是,不要让交互式 mysql会话在未提交事务的情况下长时间处于打开状态。
如果使用锁定读取(SELECT
... FOR UPDATE或
SELECT ... LOCK IN SHARE
MODE),请尝试使用较低的隔离级别,例如
READ COMMITTED。
在事务中修改多个表或同一表中的不同行时,每次都要以一致的顺序执行这些操作。然后事务形成明确定义的队列并且不会发生死锁。例如,组织数据库操作到功能在应用程序中,或调用存储程序,而不是编码的多个相似序列
INSERT,UPDATE以及
DELETE在不同的地方语句。
将精心挑选的索引添加到表格中。然后,您的查询需要扫描更少的索引记录,从而设置更少的锁。使用EXPLAIN
SELECT以确定哪些索引MySQL认为最适合您的查询。
使用更少的锁定。如果您可以承诺允许
SELECT从旧快照返回数据,请不要添加该子句FOR
UPDATE或添加该子句LOCK IN SHARE MODE。在READ
COMMITTED这里使用隔离级别是很好的,因为在同一事务中每次一致的读取都会从它自己的新快照中读取。
如果没有其他帮助,请使用表级锁定序列化您的事务。LOCK TABLES与事务表(如InnoDB
表)一起使用的正确方法是使用
SET
autocommit = 0(not
START
TRANSACTION)开头事务LOCK
TABLES,并且UNLOCK
TABLES在显式提交事务之前不要调用
。例如,如果您需要写入表格
t1并从表格中读取
t2,则可以这样做:
SET autocommit = 0;
锁定表t1写,t2读,...;
... do something with tables t1 and t2 here ...
承诺;
解锁表;
表级锁定可防止对表进行并发更新,从而避免死锁,但会降低对繁忙系统的响应速度。
序列化事务的另一种方法是创建一个仅包含单行的辅助“ 信号量 ”表。在访问其他表之前,让每个事务更新该行。这样,所有的交易都是以串行的方式进行的。请注意,InnoDB
即时死锁检测算法也适用于这种情况,因为序列化锁是行级锁。使用MySQL表级锁定时,必须使用超时方法来解决死锁问题。
本节提供有关存储引擎的InnoDB初始化,启动以及各种组件和功能的配置信息和过程
InnoDB。有关优化InnoDB表的数据库操作的信息
,请参见
第8.5节“优化InnoDB表”。
关于InnoDB
配置的第一个决定涉及数据文件,日志文件,页面大小和内存缓冲区的配置。建议您在创建InnoDB实例之前定义数据文件,日志文件和页面大小配置。在InnoDB创建实例后修改数据文件或日志文件配置可能涉及一个非平凡的过程,并且页面大小只能在InnoDB实例初次初始化时定义。
除这些主题外,本节还提供有关指定InnoDB配置文件中的选项,查看InnoDB
初始化信息以及重要的存储注意事项的信息。
由于MySQL使用数据文件,日志文件和页面大小配置设置来初始化
InnoDB实例,因此建议您InnoDB在初次启动之前在启动时读取的配置文件中定义这些设置。InnoDB在MySQL服务器启动时初始化,第一次初始化
InnoDB通常在第一次启动MySQL服务器时发生。
您可以将InnoDB选项放置在[mysqld]服务器启动时读取的任何选项文件的
组中。MySQL选项文件的位置在第4.2.6节“使用选项文件”中介绍。
要确保mysqld仅从特定文件读取选项,请--defaults-file在启动服务器时使用该
选项作为命令行中的第一个选项:
mysqld --defaults-file =path_to_configuration_file
要InnoDB在启动过程中查看初始化信息,请从命令提示符处启动mysqld。当从命令提示符启动mysqld时,初始化信息将打印到控制台。
例如,在Windows上,如果mysqld位于C:\Program Files\MySQL\MySQL Server
5.7\bin,请启动MySQL服务器,如下所示:
C:\> "C:\Program Files\MySQL\MySQL Server 5.7\bin\mysqld" --console
在类Unix系统上,mysqld位于binMySQL安装目录中:
外壳> bin/mysqld --user=mysql &
如果您没有将服务器输出发送到控制台,请在启动后检查错误日志以查看InnoDB在启动过程中打印的初始化信息
。
有关使用其他方法启动MySQL的信息,请参见 第2.10.5节“自动启动和停止MySQL”。
InnoDB在启动时不打开所有用户表和关联的数据文件。但是,
InnoDB它会检查*.ibd数据字典中引用的表空间文件(文件)的存在。如果找不到表空间文件,则InnoDB记录错误并继续启动顺序。重做日志中引用的表空间文件可能在重做应用程序的崩溃恢复期间打开。
继续进行启动配置之前,请查看以下与存储相关的注意事项。
在某些情况下,如果数据未全部放置在同一物理磁盘上,数据库性能会提高。将日志文件放在与数据不同的磁盘上通常对性能有利。例如,您可以将系统表空间数据文件和日志文件放在不同的磁盘上。您还可以将原始磁盘分区(原始设备)用于
InnoDB数据文件,这可能会加速I / O。请参见第14.7.3节“为系统表空间使用原始磁盘分区”。
InnoDB是MySQL的事务安全(ACID兼容)存储引擎,具有提交,回滚和崩溃恢复功能来保护用户数据。但是,如果底层操作系统或硬件不能像宣传的那样工作,则不能这样做。许多操作系统或磁盘子系统可能会延迟或重新排序写入操作以提高性能。在一些操作系统上,非常
fsync()系统调用应该等到文件的所有未写入数据已被刷新后,实际上可能会在数据刷新到稳定存储之前返回。因此,操作系统崩溃或停电可能会破坏最近提交的数据,或者在最糟糕的情况下,由于写入操作被重新排序,甚至会损坏数据库。如果数据完整性对您很重要,请
在生产中使用任何内容之前执行一些“ 拔插 ”测试。在OS X 10.3及更高版本上,InnoDB使用特殊的
fcntl()文件冲洗方法。在Linux下,建议禁用写回缓存。
在ATA / SATA磁盘驱动器上,这样的命令hdparm -W0
/dev/hda可能会禁用写回缓存。
请注意,某些驱动器或磁盘控制器可能无法禁用写回缓存。
关于InnoDB保护用户数据的恢复功能,
InnoDB使用涉及称为双写缓冲区的结构的文件刷新技术,该结构
默认为启用(innodb_doublewrite=ON)。双重写入缓冲区增加了崩溃或断电后恢复的安全性,并通过减少fsync()操作需求提高了大多数Unix系统的性能
。innodb_doublewrite
如果您关心数据完整性或可能的故障,建议您保持启用该选项。有关doublewrite缓冲区的更多信息,请参阅
第14.12.1节“InnoDB磁盘I / O”。
在使用NFS之前InnoDB,请查看使用NFS与MySQL中概述的潜在问题
。
在Windows上的4K扇区硬盘上运行MySQL服务器不支持
innodb_flush_method=async_unbuffered,这是默认设置。解决方法是使用
innodb_flush_method=normal。
的innodb_data_file_path
配置选项定义的名称,大小,和属性
InnoDB系统表空间的数据文件。如果您未指定值
innodb_data_file_path,则默认行为是创建一个自动扩展数据文件,该文件略大于12MB,即已命名ibdata1。
要指定多个数据文件,请用分号(;)字符分隔它们:
innodb_data_file_path =datafile_spec1[;datafile_spec2] ...
以下设置配置了一个名为“ ibdata1自动扩展” 的单个12MB数据文件
。没有给出文件的位置,所以默认情况下,InnoDB
在MySQL数据目录中创建它:
的[mysqld] innodb_data_file_path中= ibdata1中:12M:自动扩展
文件大小使用K,M或G后缀字母指定,
以指示KB,MB或GB的单位。如果以千字节(KB)为单位指定数据文件大小,请以1024的倍数进行此操作。否则,将KB值四舍五入为最接近兆字节(MB)的边界。文件大小的总和必须至少略大于12MB。
为第一个系统表空间数据文件强制执行最小文件大小, 以确保有足够的空间存储双倍缓冲页面:
对于innodb_page_size
16KB或更小的值,最小文件大小为3MB。
对于innodb_page_size
32KB 的值,最小文件大小为6MB。
对于innodb_page_size
64KB 的值,最小文件大小为12MB。
可以像这样配置ibdata1一个
名为固定大小的50MB数据文件和一个50MB自动扩展文件的系统表空间
ibdata2:
的[mysqld] innodb_data_file_path中= ibdata1中:50M; ibdata2:50M:自动扩展
一个数据文件规范完整的语法包括文件名,文件大小,以及可选的autoextend和
max属性:
file_name:file_size[:autoextend [:max:max_file_size]]
该autoextend和max
属性只能用于将最后一个指定的数据文件中使用
innodb_data_file_path的设置。
如果您autoextend为最后一个数据文件指定了选项,那么InnoDB扩展数据文件(如果它在表空间中的空闲空间不足)。该
autoextend增量是在默认情况下,时间64MB。要修改增量,请更改
innodb_autoextend_increment
系统变量。
如果磁盘已满,则可能需要在另一个磁盘上添加另一个数据文件。有关说明,请参见 第14.7.1节“调整InnoDB系统表空间的大小”。
单个文件的大小限制取决于您的操作系统。在支持大文件的操作系统上,您可以将文件大小设置为4GB以上。您还可以 使用原始磁盘分区作为数据文件。
InnoDB不知道文件系统的最大文件大小,因此请谨慎处理最大文件大小为2GB等较小值的文件系统。要指定自动扩展数据文件的最大大小,请使用
max属性后面的
autoextend属性。max仅在限制磁盘使用率至关重要的情况下使用该
属性,因为超过最大大小会导致致命错误,可能导致服务器退出。以下配置允许
ibdata1增长到500MB的限制:
的[mysqld] innodb_data_file_path中= ibdata1中:12M:自动扩展:最大:500M
InnoDB默认情况下(datadir),在MySQL数据目录中创建系统表空间文件。要明确指定位置,请使用该
innodb_data_home_dir选项。例如,要在名为的目录中创建两个名为的文件
ibdata1,请ibdata2按如下所示进行myibdata配置
InnoDB:
的[mysqld] innodb_data_home_dir = / path / to / myibdata / innodb_data_file_path中= ibdata1中:50M; ibdata2:50M:自动扩展
指定值时需要尾部斜线
innodb_data_home_dir。
InnoDB不会创建目录,因此myibdata在启动服务器之前请确保目录存在。使用Unix或DOS
mkdir命令创建目录。
确保MySQL服务器具有在数据目录中创建文件的正确访问权限。更一般地说,服务器必须在任何需要创建数据文件的目录中拥有访问权限。
InnoDB通过将数值文件连接innodb_data_home_dir到数据文件名称来形成每个数据文件的目录路径
。如果innodb_data_home_dir未指定该
选项,则默认值为“ dot ”
目录./,这表示MySQL数据目录。(MySQL服务器在开始执行时将其当前工作目录更改为其数据目录。)
如果您指定
innodb_data_home_dir为空字符串,则可以为innodb_data_file_path值中列出的数据文件指定绝对路径
。以下示例等同于上述示例:
的[mysqld] innodb_data_home_dir = innodb_data_file_path中= /路径/到/ myibdata / ibdata1中:50M; /路径/到/ myibdata / ibdata2:50M:自动扩展
默认情况下,InnoDB在MySQL数据目录(datadir)中创建两个48MB的日志文件named
ib_logfile0和
ib_logfile1。
以下选项可用于修改默认配置:
innodb_log_group_home_dir
定义InnoDB日志文件的目录路径(重做日志)。如果未配置此选项,
InnoDB则会在MySQL数据目录(datadir)中创建日志文件。
您可以使用此选项将InnoDB
日志文件放置在与InnoDB数据文件不同的物理存储位置,
以避免潜在的I / O资源冲突。例如:
的[mysqld] innodb_log_group_home_dir = / dr3 / iblogs
InnoDB不会创建目录,因此在启动服务器之前请确保日志目录存在。使用Unix或DOS mkdir
命令创建任何必需的目录。
确保MySQL服务器具有在日志目录中创建文件的正确访问权限。更一般地说,服务器必须在任何需要创建日志文件的目录中拥有访问权限。
innodb_log_files_in_group
定义日志组中的日志文件数量。默认值和推荐值是2。
innodb_log_file_size
定义日志组中每个日志文件的字节大小。日志文件的组合大小(innodb_log_file_size*
innodb_log_files_in_group)不能超过略小于512GB的最大值。例如,一对255 GB的日志文件接近极限,但不超过它。默认的日志文件大小为48MB。通常,日志文件的组合大小应该足够大,以便服务器可以消除工作负载活动中的高峰和低谷,这通常意味着有足够的重做日志空间来处理一个多小时的写入活动。值越大,缓冲池中所需的检查点刷新活动就越少,从而节省磁盘I / O。有关更多信息,请参见
第8.5.4节“优化InnoDB重做日志记录”。
默认情况下,InnoDB撤消日志是系统表空间的一部分。但是,您可以选择将InnoDB撤消日志存储
在一个或多个单独的撤消表空间中,通常位于不同的存储设备上。
的innodb_undo_directory
配置选项定义了路径
InnoDB创建撤消日志分开的表空间。此选项通常与innodb_rollback_segments和
innodb_undo_tablespaces
选项一起使用
,这些选项决定了系统表空间外的撤销日志的磁盘布局。
innodb_undo_tablespaces 已弃用,将在未来版本中删除。
有关更多信息,请参见 部分14.7.7,“配置撤消表空间”。
默认情况下,InnoDB创建一个名为的自动扩展临时表空间数据文件ibtmp1,该文件
在innodb_data_home_dir
目录中略大于12MB 。使用innodb_temp_data_file_path
配置选项可以在启动时修改默认的临时表空间数据文件配置
。
该innodb_temp_data_file_path
选项指定InnoDB临时表空间数据文件的路径,文件名和文件大小
。文件的完整目录路径通过连接innodb_data_home_dir到指定的路径
形成
innodb_temp_data_file_path。通过将K,M或G附加到大小值中指定文件大小,以KB,MB或GB(1024MB)表示。文件大小的总和必须略大于12MB。
该innodb_data_home_dir
默认值是MySQL数据目录(datadir)。
该innodb_page_size选项指定InnoDB
MySQL实例中所有表空间的页面大小。该值在创建实例时设置,并在此后保持不变。有效值为64k,32k,16k(默认值),8k和4k。或者,您可以以字节为单位指定页面大小(65536,32768,16384,8192,4096)。
16k的默认页面大小适用于各种工作负载,特别是涉及涉及批量更新的表扫描和DML操作的查询。对于涉及许多小写入的OLTP工作负载,较小的页面大小可能更有效,当单个页面包含多行时,争用可能成为问题。较小的页面对于SSD存储设备也可能是有效的,SSD存储设备通常使用小块大小。保持InnoDB页面大小接近存储设备块大小可将重写到磁盘的未更改数据量减至最少。
MySQL为各种缓存和缓冲区分配内存以提高数据库操作的性能。在分配内存时
InnoDB,请始终考虑操作系统所需的内存,分配给其他应用程序的内存以及分配给其他MySQL缓冲区和缓存的内存。例如,如果您使用MyISAM表格,请考虑为键缓冲区(key_buffer_size)分配的内存量。有关MySQL缓冲区和缓存的概述,请参见
第8.12.4.1节“MySQL如何使用内存”。
特定的缓冲区InnoDB使用以下参数进行配置:
innodb_buffer_pool_size
定义缓冲池的大小,缓冲池是保存InnoDB表,索引和其他辅助缓冲区的缓存数据的内存区域。缓冲池的大小对系统性能很重要,通常建议将
innodb_buffer_pool_size其配置为系统内存的50%到75%。默认缓冲池大小为128MB。有关更多指导,请参见
第8.12.4.1节“MySQL如何使用内存”。有关如何配置InnoDB缓冲池大小的信息,请参见
第14.6.3.2节“配置InnoDB缓冲池大小”。缓冲池大小可以在启动时或动态配置。
在具有大量内存的系统上,可以通过将缓冲池分为多个缓冲池实例来提高并发性。缓冲池实例的数量由by innodb_buffer_pool_instances
选项控制
。默认情况下,InnoDB创建一个缓冲池实例。缓冲池实例的数量可以在启动时配置。有关更多信息,请参见
第14.6.3.3节“配置多个缓冲池实例”。
innodb_log_buffer_size
定义InnoDB用于写入磁盘日志文件的缓冲区大小(以字节为单位)
。默认大小是16MB。大型日志缓冲区允许大型事务运行,而无需在事务提交之前将日志写入磁盘。如果您有更新,插入或删除多行的事务,则可以考虑增加日志缓冲区的大小以节省磁盘I / O。
innodb_log_buffer_size可以在启动时配置。有关相关信息,请参见
第8.5.4节“优化InnoDB重做日志”。
在32位GNU / Linux x86上,请注意不要将内存使用设置得太高。glibc可能会允许进程堆扩展到线程堆栈,这会导致服务器崩溃。分配给
全局和每线程缓冲区和缓存的mysqld进程的内存接近或超过2GB 是一种风险。
用于计算MySQL的全局和每线程内存分配的类似以下公式可用于估计MySQL内存使用情况。您可能需要修改公式来考虑MySQL版本和配置中的缓冲区和缓存。有关MySQL缓冲区和缓存的概述,请参见第8.12.4.1节“MySQL如何使用内存”。
innodb_buffer_pool_size + key_buffer_size + max_connections *(sort_buffer_size + read_buffer_size + binlog_cache_size) + max_connections * 2MB
每个线程使用一个堆栈(通常是2MB,但在Oracle公司提供的MySQL二进制文件中只有256KB),最坏的情况下也使用sort_buffer_size +
read_buffer_size额外的内存。
在Linux上,如果内核启用了大页面支持,则
InnoDB可以使用大页面为其缓冲池分配内存。请参见第8.12.4.2节“启用大页面支持”。
您现在可以InnoDB通过--innodb-read-only在服务器启动时启用配置选项来查询MySQL数据目录位于只读介质上的表
。
要为只读操作准备实例,请确保在
将数据文件存储在只读介质之前将所有必要信息刷新到数据文件。使用更改缓冲禁用(innodb_change_buffering=0)运行服务器并执行缓慢关机。
要为整个MySQL实例启用只读模式,请在服务器启动时指定以下配置选项:
如果该实例位于只读介质(例如DVD或CD)上,或该/var目录不可写入所有:
和--pid-file=path_on_writeable_media--event-scheduler=disabled
--innodb_temp_data_file_path。该选项指定InnoDB临时表空间数据文件的路径,文件名和文件大小
。默认设置是ibtmp1:12M:autoextend,它ibtmp1在数据目录中创建临时表空间数据文件。要为只读操作准备实例,请将其设置
innodb_temp_data_file_path为数据目录之外的位置。路径必须相对于数据目录; 例如:
--innodb_temp_data_file_path = .. / .. / .. / TMP / ibtmp1:12M:自动扩展
这种操作模式适用于以下情况:
在只读存储介质(如DVD或CD)上分发MySQL应用程序或一组MySQL数据。
多个MySQL实例同时查询同一个数据目录,通常在数据仓库配置中。您可以使用这种技术来避免 可能发生的负载较重的MySQL实例的瓶颈问题,也可以使用不同的配置选项来针对各种实例调整每种查询的特定类型的查询。
由于安全或数据完整性原因(例如归档备份数据),查询已进入只读状态的数据。
此功能主要用于分发和部署的灵活性,而不是基于只读方面的原始性能。有关调整只读查询性能的方法,请参见 第8.5.3节“优化InnoDB只读事务”,该方法不需要使整个服务器只读。
当服务器通过--innodb-read-only选项以只读模式运行时
,某些InnoDB功能和组件将被完全减少或关闭:
没有改变缓冲完成,特别是没有从更改缓冲区合并。为了确保在为只读操作准备实例时更改缓冲区为空,请禁用更改缓冲(innodb_change_buffering=0)并首先执行缓慢关闭。
由于重做日志未用于只读操作,innodb_log_file_size因此在将实例设置为只读之前,可以将其设置
为尽可能最小的大小(1 MB)。
除I / O读取线程之外的所有后台线程均被关闭。因此,只读实例不会遇到任何死锁。
有关死锁,监视器输出等的信息不会写入临时文件。因此,
SHOW ENGINE
INNODB STATUS不会产生任何输出。
如果MySQL服务器已启动,
--innodb-read-only但数据目录仍在可写介质上,则root用户仍可执行DCL操作,例如GRANT和
REVOKE。
当服务器处于只读模式时,对通常会更改写入操作行为的配置选项设置的更改不起作用。
该撤消日志不被使用。禁用innodb_undo_tablespaces和
innodb_undo_directory
配置选项的任何设置
。
本节提供InnoDB缓冲池的配置和调优信息
。
InnoDB维护一个称为缓冲池的存储区域,
用于在内存中缓存数据和索引。了解InnoDB缓冲池如何
工作,并利用它来将频繁访问的数据保存在内存中,这是MySQL调优的一个重要方面。有关InnoDB缓冲池如何工作的信息,请参阅
InnoDB缓冲池LRU算法。
您可以配置InnoDB缓冲池的各个方面
以提高性能。
理想情况下,您可以将缓冲池的大小设置为尽可能大的值,从而为服务器上的其他进程留出足够的内存以在没有过多分页的情况下运行。缓冲池越大,InnoDB
就像内存数据库一样,从磁盘读取数据一次,然后在随后的读取过程中从内存中访问数据。请参见第14.6.3.2节“配置InnoDB缓冲池大小”。
对于具有大内存大小的64位系统,您可以将缓冲池分成多个部分,以最大限度地减少并发操作之间的内存结构争用。有关细节,请参见第14.6.3.3节“配置多个缓冲池实例”。
尽管备份或报告等操作突然出现活动高峰,您仍可以将经常访问的数据保留在内存中。有关详细信息,请参见 第14.6.3.4节“使缓冲池抗扫描”。
您可以控制何时以及如何InnoDB
执行预读请求,以便异步预先将页面预取到缓冲池中,因为预计这些页面很快就会被使用。有关详细信息,请参见
第14.6.3.5节“配置InnoDB缓冲池预取(预读)”。
您可以控制何时发生脏页面的后台刷新,以及是否InnoDB
根据工作负载动态调整刷新率。有关细节,请参见
第14.6.3.6节“配置InnoDB缓冲池刷新”。
您可以微调InnoDB
缓冲池刷新行为的各个方面以提高性能。有关细节,请参见
第14.6.3.7节“微调InnoDB缓冲池刷新”。
您可以配置如何InnoDB保留当前缓冲池状态以避免重新启动服务器之后长时间的热身期。您也可以在服务器运行时保存当前的缓冲池状态。有关详细信息,请参见第14.6.3.8节“保存和恢复缓冲池状态”。
InnoDB使用最近最少使用(LRU)算法的变体将缓冲池作为列表来管理。当需要空间将新页面添加到池中时,会
InnoDB清除最近最少使用的页面,并将新页面添加到列表的中间。这种
“ 中点插入策略 ”将列表视为两个子列表:
头部是最近访问的“ 新 ”(或 “ 年轻 ”)页面的子列表。
尾部是最近访问过的“ 旧 ”页面的子列表。
该算法保留了新子列表中查询大量使用的页面。旧的子列表包含较少使用的页面; 这些网页是驱逐的候选人 。
LRU算法默认运行如下:
3/8的缓冲池专用于旧的子列表。
列表的中点是新子列表的尾部与旧子列表的头部相交的边界。
当InnoDB将页面读入缓冲池时,它最初将其插入到中点(旧子列表的头部)。可以读入页面,因为它是用户指定的操作(例如SQL查询)所必需的,或者作为
自动执行的预读操作的
一部分
InnoDB。
在旧的子列表中访问一个页面会使其变得 “ 年轻 ”,将其移动到缓冲池的头部(新子列表的头部)。如果页面因为需要而被读入,则第一次访问立即发生并且页面变得年轻。如果由于预读而导致页面被读入,则第一次访问不会立即发生(并且在页面被逐出之前可能根本不会发生)。
随着数据库的运行,在缓冲池的页面没有被访问的“ 年龄 ”通过向列表的尾部移动。新的和旧的子列表中的页面随着其他页面的变化而变旧。在中点插入页面时,旧子列表中的页面也会变老。最终,一段长时间未使用的页面会到达旧的子列表的尾部并被驱逐。
默认情况下,查询读取的页面会立即移动到新的子列表中,这意味着它们会留在缓冲池中的时间更长。表扫描(例如为mysqldump操作执行,或者
执行
SELECT不带
WHERE子句的语句)可以将大量数据带入缓冲池并驱逐相当数量的旧数据,即使新数据从不再使用。同样,由预读后台线程加载,然后只访问一次的页面移动到新列表的头部。这些情况可能会将经常使用的页面推送到旧的子列表中,他们可能会受到驱逐。有关优化此行为的信息,请参阅
第14.6.3.4节“使缓冲池抗扫描”和
第14.6.3.5节“配置InnoDB缓冲池预取(预读)”。
InnoDB标准监视器输出包含BUFFER POOL AND
MEMORY与缓冲池LRU算法的操作有关的部分中的几个字段。有关详细信息,请参见
第14.6.3.9节“使用InnoDB标准监视器监视缓冲池”。
几个配置选项影响InnoDB缓冲池的不同方面
。
指定缓冲池的大小。如果缓冲池很小并且有足够的内存,则通过减少作为查询访问InnoDB表所需的磁盘I / O量,使缓冲池变大可以提高性能
。该
innodb_buffer_pool_size
选项是动态的,可让您在不重新启动服务器的情况下配置缓冲池大小。有关更多信息,请参见
第14.6.3.2节“配置InnoDB缓冲池大小”。
innodb_buffer_pool_chunk_size
定义InnoDB
缓冲池调整大小操作的块大小。有关更多信息,请参见
第14.6.3.2节“配置InnoDB缓冲池大小”。
将缓冲池划分为用户指定数量的单独区域,每个区域都有自己的LRU列表和相关数据结构,以减少并发内存读取和写入操作期间的争用。此选项仅在设置innodb_buffer_pool_size
为1GB或更大的值时才会生效
。您指定的总大小被分配到所有缓冲池中。为了获得最佳效率,指定的组合
innodb_buffer_pool_instances
和
innodb_buffer_pool_size
,使得每个缓冲池实例是至少1千兆字节。有关更多信息,请参见第14.6.3.3节“配置多个缓冲池实例”。
指定InnoDB用于旧块子列表的缓冲池的近似百分比。值的范围是5到95.默认值是37(即池的3/8)。有关
更多信息,请参见
第14.6.3.4节“使缓冲池抗扫描”。
指定插入到旧子表中的页面以毫秒(ms)为单位的时间长度 必须在第一次访问后留在那里,然后才能移动到新的子列表中。如果值为0,则无论插入后何时发生访问,插入旧子列表的页面在第一次访问时都会立即移至新子列表。如果该值大于0,则页面将保留在旧的子列表中,直到第一次访问后至少几毫秒才会发生访问。例如,值为1000会导致页面在第一次访问后停留在旧子表中1秒钟,然后才有资格移动到新子列表。
如果设置为
innodb_old_blocks_time
大于0,则防止一次性表扫描使用仅用于扫描的页面填充新的子列表。读取的扫描页面中的行会连续快速访问多次,但该页面在此之后未被使用。如果
innodb_old_blocks_time设置的值大于处理页面的时间,则该页面会保留在“ 旧 ”子列表中,并且会延迟到列表尾部以便快速驱逐。这样,仅用于一次扫描的页面不会影响新子列表中大量使用的页面。
innodb_old_blocks_time
可以在运行时设置,因此您可以在执行诸如表扫描和转储等操作时临时更改它:
SET GLOBAL innodb_old_blocks_time = 1000;
... perform queries that scan tables ...
SET GLOBAL innodb_old_blocks_time = 0;
如果你的目的是这种策略并不适用
“ 热身 ”用表的内容填充它的缓冲池。例如,基准测试通常在服务器启动时执行表或索引扫描,因为在正常使用一段时间后,数据通常会在缓冲池中。在这种情况下,innodb_old_blocks_time
至少在暖机阶段完成之前,请将其
设置为0。
有关 更多信息,请参见 第14.6.3.4节“使缓冲池抗扫描”。
控制线性的灵敏度
预读的是
InnoDB使用预取页入缓冲池。
有关更多信息,请参见第14.6.3.5节“配置InnoDB缓冲池预取(预读)”。
使用随机
预读技术将页面预取到缓冲池中。随机预读是一种技术,可根据缓冲池中已有的页面快速预测何时需要页面,而不管这些页面的读取顺序如何。
innodb_random_read_ahead
在默认情况下被禁用。
有关更多信息,请参见第14.6.3.5节“配置InnoDB缓冲池预取(预读)”。
指定是否根据工作负载动态调整缓冲池中刷新脏页的速率。动态调整冲刷速率旨在避免I / O活动的爆发。该设置默认启用。
有关 更多信息,请参见第14.6.3.6节“配置InnoDB缓冲池刷新”。
有关更多信息,请参见第14.6.3.7节“微调InnoDB缓冲池刷新”。
指定是否 冲洗从缓冲池页面也可以清空其他 脏页在相同的程度。
有关更多信息,请参见第14.6.3.7节“微调InnoDB缓冲池刷新”。
InnoDB保持以前计算的刷新状态快照的迭代次数,控制自适应刷新对变化工作负载的响应 速度。
有关更多信息,请参见第14.6.3.7节“微调InnoDB缓冲池刷新”。
影响缓冲池刷新操作的算法和启发式的参数。性能专家主要关注调整I / O密集型工作负载。它指定每个缓冲池实例在缓冲池LRU下多远列出page_cleaner线程扫描寻找要刷新的脏页。
有关更多信息,请参见第14.6.3.7节“微调InnoDB缓冲池刷新”。
InnoDB尝试
从缓冲池中清除数据,以便脏页面的百分比
不超过此值。指定范围从0到99的整数。默认值为75。
有关 更多信息,请参见第14.6.3.6节“配置InnoDB缓冲池刷新”。
innodb_max_dirty_pages_pct_lwm
低水位较百分比 脏页,其中预冲洗能够控制脏页比例。默认值为0将完全禁用预冲洗行为。
有关更多信息,请参见第14.6.3.7节“微调InnoDB缓冲池刷新”。
指定保存由innodb_buffer_pool_dump_at_shutdown
or
生成的表空间ID和页面ID列表的文件的名称
innodb_buffer_pool_dump_now。
有关更多信息,请参见第14.6.3.8节“保存和恢复缓冲池状态”。
innodb_buffer_pool_dump_at_shutdown
指定在MySQL服务器关闭时是否记录缓冲池中缓存的页面,以缩短下次重新启动时的 预热过程。
有关更多信息,请参见第14.6.3.8节“保存和恢复缓冲池状态”。
innodb_buffer_pool_load_at_startup
指定在MySQL服务器启动时,通过加载它在先前保存的相同页面,缓冲池自动预热。通常与...结合使用
innodb_buffer_pool_dump_at_shutdown。
有关更多信息,请参见第14.6.3.8节“保存和恢复缓冲池状态”。
立即记录在缓冲池中缓存的页面。
有关更多信息,请参见第14.6.3.8节“保存和恢复缓冲池状态”。
立即
通过加载一组数据页面来加热缓冲池,而无需等待服务器重新启动。在基准测试期间将高速缓存恢复到已知状态,或者在运行查询报告或维护后,使MySQL服务器恢复正常工作负载,可能会很有用。通常使用
innodb_buffer_pool_dump_now。
有关更多信息,请参见第14.6.3.8节“保存和恢复缓冲池状态”。
指定每个缓冲池读出和转储的最近使用页面的百分比。范围是1到100。
有关更多信息,请参见第14.6.3.8节“保存和恢复缓冲池状态”。
中断恢复由innodb_buffer_pool_load_at_startup
或
触发的缓冲池内容的过程
innodb_buffer_pool_load_now。
有关更多信息,请参见第14.6.3.8节“保存和恢复缓冲池状态”。
您可以InnoDB在服务器运行时配置缓冲池大小(在启动时)或联机。本节中描述的行为适用于这两种方法。有关在线配置缓冲池大小的更多信息,请参阅在线配置InnoDB缓冲池大小。
在增加或减少时
innodb_buffer_pool_size,操作以块为单位执行。块大小由innodb_buffer_pool_chunk_size
配置选项定义,该
选项默认为
128M。有关更多信息,请参阅
配置InnoDB缓冲池块大小。
缓冲池大小必须始终等于或innodb_buffer_pool_chunk_size*
的倍数
innodb_buffer_pool_instances。如果配置innodb_buffer_pool_size的值不等于或等于innodb_buffer_pool_chunk_size*
的倍数,
则将
innodb_buffer_pool_instances缓冲池大小自动调整为等于或
不小于指定缓冲池大小的innodb_buffer_pool_chunk_size*
的倍数
innodb_buffer_pool_instances。
在以下示例中,
innodb_buffer_pool_size设置为8G并
innodb_buffer_pool_instances设置为16。
innodb_buffer_pool_chunk_size
是128M,这是默认值。
8G是一个有效的
innodb_buffer_pool_size值,因为它是
*
8G的倍数
,也就是。
innodb_buffer_pool_instances=16innodb_buffer_pool_chunk_size=128M2G
外壳> mysqld --innodb_buffer_pool_size=8G --innodb_buffer_pool_instances=16
MySQL的> SELECT @@innodb_buffer_pool_size/1024/1024/1024;
+ ------------------------------------------ +
| @@ innodb_buffer_pool_size / 1024/1024/1024 |
+ ------------------------------------------ +
| 8.000000000000 |
+ ------------------------------------------ +
在这个例子中,
innodb_buffer_pool_size设置为9G,并
innodb_buffer_pool_instances设置为16。
innodb_buffer_pool_chunk_size
是128M,这是默认值。在这种情况下,9G不是innodb_buffer_pool_instances=16
* 的倍数
innodb_buffer_pool_chunk_size=128M,因此innodb_buffer_pool_size被调整为*
,10G这是innodb_buffer_pool_chunk_size*
的下一个倍数
innodb_buffer_pool_instances
不小于指定的缓冲池大小。
外壳> mysqld --innodb_buffer_pool_size=9G --innodb_buffer_pool_instances=16
MySQL的> SELECT @@innodb_buffer_pool_size/1024/1024/1024;
+ ------------------------------------------ +
| @@ innodb_buffer_pool_size / 1024/1024/1024 |
+ ------------------------------------------ +
| 10.000000000000 |
+ ------------------------------------------ +
innodb_buffer_pool_chunk_size
可以以1MB(1048576字节)为单位增加或减少,但只能在启动时,命令行字符串或MySQL配置文件中修改。
命令行:
外壳> mysqld --innodb_buffer_pool_chunk_size=134217728
配置文件:
的[mysqld] innodb_buffer_pool_chunk_size = 134217728
更改时适用以下条件
innodb_buffer_pool_chunk_size:
如果在
缓冲池初始化时新
innodb_buffer_pool_chunk_size值*
innodb_buffer_pool_instances大于当前缓冲池大小,
innodb_buffer_pool_chunk_size
则会截断为
innodb_buffer_pool_size/
innodb_buffer_pool_instances。
例如,如果缓冲池的初始化大小为2GB(2147483648字节),
4缓冲池实例和块大小1GB(1073741824字节),则块大小会截断为等于innodb_buffer_pool_size/
的值
innodb_buffer_pool_instances,如下所示:
外壳>mysqld --innodb_buffer_pool_size=2147483648 --innodb_buffer_pool_instances=4--innodb_buffer_pool_chunk_size=1073741824;
MySQL的>SELECT @@innodb_buffer_pool_size;+ --------------------------- + | @@ innodb_buffer_pool_size | + --------------------------- + | 2147483648 | + --------------------------- + MySQL的>SELECT @@innodb_buffer_pool_instances;+ -------------------------------- + | @@ innodb_buffer_pool_instances | + -------------------------------- + | 4 | + -------------------------------- + #启动时块大小设置为1GB(1073741824字节),但是 #截断到innodb_buffer_pool_size / innodb_buffer_pool_instances MySQL的>SELECT @@innodb_buffer_pool_chunk_size;+ --------------------------------- + | @@ innodb_buffer_pool_chunk_size | + --------------------------------- + | 536870912 | + --------------------------------- +
缓冲池大小必须始终等于或innodb_buffer_pool_chunk_size
*
的倍数
innodb_buffer_pool_instances。如果更改
innodb_buffer_pool_chunk_size,
innodb_buffer_pool_size
将自动调整为等于或
不小于当前缓冲池大小的innodb_buffer_pool_chunk_size
*
的倍数
innodb_buffer_pool_instances。调整发生在缓冲池初始化时。以下示例演示了此行为:
#缓冲池的默认大小为128MB(134217728字节) MySQL的>SELECT @@innodb_buffer_pool_size;+ --------------------------- + | @@ innodb_buffer_pool_size | + --------------------------- + | 134217728 | + --------------------------- + #块大小也是128MB(134217728字节) MySQL的>SELECT @@innodb_buffer_pool_chunk_size;+ --------------------------------- + | @@ innodb_buffer_pool_chunk_size | + --------------------------------- + | 134217728 | + --------------------------------- + #有一个单独的缓冲池实例 MySQL的>SELECT @@innodb_buffer_pool_instances;+ -------------------------------- + | @@ innodb_buffer_pool_instances | + -------------------------------- + | 1 | + -------------------------------- + #启动时块大小减少1MB(1048576字节) #(134217728 - 1048576 = 133169152): 外壳>mysqld --innodb_buffer_pool_chunk_size=133169152MySQL的>SELECT @@innodb_buffer_pool_chunk_size;+ --------------------------------- + | @@ innodb_buffer_pool_chunk_size | + --------------------------------- + | 133169152 | + --------------------------------- + #缓冲池大小从134217728增加到266338304 #缓冲池大小自动调整为等于的值 #或innodb_buffer_pool_chunk_size * innodb_buffer_pool_instances的倍数 #不小于当前缓冲池大小 MySQL的>SELECT @@innodb_buffer_pool_size;+ --------------------------- + | @@ innodb_buffer_pool_size | + --------------------------- + | 266338304 | + --------------------------- +
此示例演示了相同的行为,但具有多个缓冲池实例:
#缓冲池的默认大小为2GB(2147483648字节) MySQL的>SELECT @@innodb_buffer_pool_size;+ --------------------------- + | @@ innodb_buffer_pool_size | + --------------------------- + | 2147483648 | + --------------------------- + #块大小为.5 GB(536870912字节) MySQL的>SELECT @@innodb_buffer_pool_chunk_size;+ --------------------------------- + | @@ innodb_buffer_pool_chunk_size | + --------------------------------- + | 536870912 | + --------------------------------- + #有4个缓冲池实例 MySQL的>SELECT @@innodb_buffer_pool_instances;+ -------------------------------- + | @@ innodb_buffer_pool_instances | + -------------------------------- + | 4 | + -------------------------------- + #启动时块大小减少1MB(1048576字节) #(536870912 - 1048576 = 535822336): 外壳>mysqld --innodb_buffer_pool_chunk_size=535822336MySQL的>SELECT @@innodb_buffer_pool_chunk_size;+ --------------------------------- + | @@ innodb_buffer_pool_chunk_size | + --------------------------------- + | 535822336 | + --------------------------------- + #缓冲池大小从2147483648增加到4286578688 #缓冲池大小自动调整为等于的值 #或innodb_buffer_pool_chunk_size * innodb_buffer_pool_instances的倍数 #不小于当前缓冲池大小2147483648 MySQL的>SELECT @@innodb_buffer_pool_size;+ --------------------------- + | @@ innodb_buffer_pool_size | + --------------------------- + | 4286578688 | + --------------------------- +
更改时应该小心
innodb_buffer_pool_chunk_size,因为更改此值可以增加缓冲池的大小,如上面的示例所示。在更改之前
innodb_buffer_pool_chunk_size,计算效果
innodb_buffer_pool_size
以确保生成的缓冲池大小可接受。
为避免潜在的性能问题,块(innodb_buffer_pool_size/
innodb_buffer_pool_chunk_size)的数量不应超过1000个。
该innodb_buffer_pool_size
配置选项可以动态使用设置
SET声明,让您调整缓冲池无需重新启动服务器。例如:
MySQL的> SET GLOBAL innodb_buffer_pool_size=402653184;
通过执行活动事务和操作
InnoDB在调整缓冲池的大小之前,应完成API。启动调整大小操作时,直到所有活动事务完成后才会启动操作。一旦调整大小操作正在进行中,需要访问缓冲池的新事务和操作必须等到调整大小操作完成。规则的例外是,当缓冲池被碎片整理时,允许对缓冲池的并发访问,并且当缓冲池大小减小时撤回页面。允许并发访问的一个缺点是它可能导致暂时缺少可用页面而页面正在被撤销。
如果在缓冲池调整大小操作开始后启动,嵌套事务可能会失败。
该
Innodb_buffer_pool_resize_status
报告缓冲池大小调整的进展。例如:
MySQL的> SHOW STATUS WHERE Variable_name='InnoDB_buffer_pool_resize_status';
+ ---------------------------------- + -------------- -------------------- +
| 变量名| 值|
+ ---------------------------------- + -------------- -------------------- +
| Innodb_buffer_pool_resize_status | 还调整其他哈希表的大小。|
+ ---------------------------------- + -------------- -------------------- +
缓冲池调整大小进度也会记录在服务器错误日志中。此示例显示增加缓冲池大小时记录的注释:
[Note] InnoDB:将缓冲池的大小从134217728调整为4294967296.(unit = 134217728) [注] InnoDB:禁用自适应散列索引。 [注意] InnoDB:缓冲池0:31块(253952块)被添加。 [注意] InnoDB:缓冲池0:哈希表被调整大小。 [注意] InnoDB:在lock_sys,自适应哈希索引,字典中调整大小的哈希表。 [注] InnoDB:完成将缓冲池的大小从134217728调整为4294967296。 [注] InnoDB:重新启用自适应哈希索引。
此示例显示减小缓冲池大小时记录的注释:
[Note] InnoDB:将缓冲池的大小从4294967296调整为134217728.(unit = 134217728) [注] InnoDB:禁用自适应散列索引。 [注] InnoDB:缓冲池0:开始撤销最后的253952块。 [注意] InnoDB:缓冲池0:从空闲列表中提取了253952个块。试图重新定位0页。 (253952分之253952) [注意] InnoDB:缓冲池0:撤销目标253952块。 [注意] InnoDB:缓冲池0:31块(253952块)被释放。 [注意] InnoDB:缓冲池0:哈希表被调整大小。 [注意] InnoDB:在lock_sys,自适应哈希索引,字典中调整大小的哈希表。 [注意] InnoDB:完成调整缓冲池从4294967296到134217728。 [注] InnoDB:重新启用自适应哈希索引。
调整大小操作由后台线程执行。当增加缓冲池的大小时,调整大小操作:
添加页面chunks(块大小由其定义
innodb_buffer_pool_chunk_size)
Coverts哈希表,列表和指针在内存中使用新地址
将新页面添加到空闲列表中
当这些操作正在进行时,其他线程将被阻止访问缓冲池。
减小缓冲池的大小时,调整大小操作:
对缓冲池进行碎片整理并撤销(释放)页面
删除页面chunks(块大小由其定义
innodb_buffer_pool_chunk_size)
转换哈希表,列表和指针以在内存中使用新地址
在这些操作中,只对缓冲池进行碎片整理和撤销页面,可以让其他线程同时访问缓冲池。
对于缓冲池在数GB范围内的系统,通过在不同线程读取和写入缓存页面时减少争用,将缓冲池划分为不同的实例可以提高并发性。此功能通常用于缓冲池大小在数GB范围内的系统。使用innodb_buffer_pool_instances
配置选项配置多个缓冲池实例
,您也可以调整该
innodb_buffer_pool_size值。
当InnoDB缓冲池很大时,可以通过从内存中检索来满足许多数据请求。您可能会遇到来自尝试一次访问缓冲池的多个线程的瓶颈。您可以启用多个缓冲池以最大限度地减少此争用。存储在缓冲池中或从中读取的每个页面都使用散列函数随机分配给其中一个缓冲池。每个缓冲池管理自己的空闲列表,刷新列表,LRU以及连接到缓冲池的所有其他数据结构,并受其自己的缓冲池互斥锁保护。
要启用多个缓冲池实例,请将innodb_buffer_pool_instances配置选项设置为
大于1(默认值)最大为64(最大值)的值。此选项只有在您设置innodb_buffer_pool_size为1GB或更大的大小时才会生效
。您指定的总大小被分配到所有缓冲池中。为了获得最佳效率,指定的组合
innodb_buffer_pool_instances
和innodb_buffer_pool_size,使得每个缓冲池实例是至少为1GB。
有关修改InnoDB缓冲池大小的信息,请参见第14.6.3.2节“配置InnoDB缓冲池大小”。
与使用严格的LRU
算法不同,InnoDB它使用一种技术来最小化导入缓冲池的数据量,
并且不会再次访问。我们的目标是确保经常访问(“ 热门 ”)的页面保留在缓冲池中,即使预读和
全表扫描
带入可能或可能未被访问的新块。
新读取的块被插入到LRU列表的中间。所有新读取的页面都插入在默认位置3/8从LRU列表尾部的位置。当页面首次在缓冲池中访问时,这些页面将移动到列表的最前面(最近使用的一端)。因此,永远不会被访问的页面永远不会将它放到LRU列表的前面,并且比使用严格的LRU方法更快地“ 老化 ”。这种安排将LRU列表分成两段,其中插入点下游的页面被认为是“ 旧 ”的,并且是LRU驱逐的理想受害者。
有关InnoDB缓冲池内部工作原理
和LRU算法细节的说明,请参见第14.6.3.1节“InnoDB缓冲池”。
您可以控制LRU列表中的插入点,并选择是否InnoDB对通过表或索引扫描进入缓冲池的块应用相同的优化。配置参数
innodb_old_blocks_pct控制LRU列表中“ 旧 ”块的百分比。默认值
innodb_old_blocks_pct是
37,对应于原始固定比例3/8。值的范围是5(缓冲池中的新页面非常快速地老化)到95
(只有5%的缓冲池是为热页面保留的,使算法接近熟悉的LRU策略)。
保持缓冲池不被预读搅动的优化可以避免由于表或索引扫描造成的类似问题。在这些扫描中,数据页面通常会连续快速访问几次,并且不会再次触摸。配置参数
innodb_old_blocks_time
指定首次访问页面之后的时间窗口(以毫秒为单位),在此期间,可以在不移动到LRU列表的前端(最近使用的末端)的情况下访问它。innodb_old_blocks_timeis
的默认值
1000。增加此值会使越来越多的块从缓冲池中快速老化。
这两个innodb_old_blocks_pct和
innodb_old_blocks_time是动态的,全球性,可以在MySQL选项文件(指定my.cnf或my.ini)在与运行时或更改SET GLOBAL
命令。更改设置需要
SUPER特权。
为了帮助您评估设置这些参数的效果,该
SHOW ENGINE INNODB STATUS命令会报告缓冲池统计信息。有关详细信息,请参见
第14.6.3.9节“使用InnoDB标准监视器监视缓冲池”。
由于这些参数的影响因硬件配置,数据和工作负载的细节而异,因此可以在基准测试中验证效果,然后在任何性能关键或生产环境中更改这些设置。
在混合工作负载中,大多数活动都是OLTP类型,并且定期批量报告查询会导致大扫描,因此在innodb_old_blocks_time批处理运行期间设置值
可以帮助保持缓冲池中正常工作负载的工作集。
扫描不能完全放入缓冲池的大型表时,设置
innodb_old_blocks_pct为较小的值会使只读取一次的数据占用大量缓冲池。例如,设置
innodb_old_blocks_pct=5将这个只读取一次的数据限制到缓冲池的5%。
扫描适合内存的小表时,在缓冲池内移动页面的开销较小,因此您可以将innodb_old_blocks_pct其保留
为默认值,甚至更高,例如
innodb_old_blocks_pct=50。
innodb_old_blocks_time
参数
的影响
比参数更难预测
innodb_old_blocks_pct
,相对较小,并且随工作量而变化更大。为了达到最佳的价值,如果调整后的性能改善innodb_old_blocks_pct不够充分,可以自行制定基准
。
一个预读请求是I / O请求预取的多个页面
缓冲池
异步,在期待这些页面将很快需要。请求在一个范围内引入所有页面
。
InnoDB使用两个预读算法来提高I / O性能:
线性预读是一项技术,可根据顺序访问的缓冲池中的页面快速预测可能需要的页面。InnoDB 通过使用配置参数调整触发异步读取请求所需的顺序页面访问次数,您可以控制何时执行预读操作
innodb_read_ahead_threshold。在添加此参数之前,InnoDB只会计算在读取当前范围的最后一页时是否对整个下一个范围发出异步预取请求。
配置参数
innodb_read_ahead_threshold
控制InnoDB检测顺序页面访问模式的敏感程度。如果从某个范围顺序读取的页数大于或等于
innodb_read_ahead_threshold,则
InnoDB启动整个后续范围的异步预读操作。
innodb_read_ahead_threshold可以设置为0-64之间的任何值。缺省值是56.值越高,访问模式检查越严格。例如,如果将该值设置为48,则InnoDB
只有在顺序访问当前范围中的48页时才会触发线性预读请求。如果值是8,InnoDB即使按顺序访问范围内的最少8页,也会触发异步预读。您可以在MySQL 配置文件中设置此参数的值,或者使用SET
GLOBAL需要SUPER特权的命令
动态更改它。
随机预读是一种技术,可根据缓冲池中已有的页面快速预测何时需要页面,而不管这些页面的读取顺序如何。如果在缓冲池中找到来自同一范围的连续13个页面,则会
InnoDB异步发出请求以预取该范围的其余页面。要启用此功能,请将配置变量设置
innodb_random_read_ahead为
ON。
该SHOW ENGINE INNODB STATUS命令显示统计信息以帮助您评估预读算法的有效性。统计数据包括以下全局状态变量的计数器信息:
这些信息在微调innodb_random_read_ahead
设置时非常有用
。
有关I / O性能的更多信息,请参见 第8.5.8节“优化InnoDB磁盘I / O”和 第8.12.2节“优化磁盘I / O”。
InnoDB在后台执行某些任务,包括冲洗
的脏页从(那些已更改但尚未写入数据库文件页)缓冲池。
InnoDB当缓冲池中脏页面的百分比达到由innodb_max_dirty_pages_pct_lwm。定义的低水印设置时,开始刷新缓冲池页面
。此选项旨在控制缓冲池中脏页的比例,并理想地防止脏页达到的百分比
innodb_max_dirty_pages_pct。如果缓冲池中脏页的百分比超过
innodb_max_dirty_pages_pct,则
InnoDB开始积极地刷新缓冲池页面。
InnoDB根据重做日志生成的速度和当前刷新率,使用算法估计所需的刷新率。其目的是通过确保缓冲区刷新活动与保持缓冲池“ 清洁 ”的需要相一致来平滑整体性能
。自动调整刷新速率有助于避免吞吐量突然下降,因为过多的缓冲池刷新限制了普通读写活动可用的I / O容量。
InnoDB以循环方式使用其日志文件。在重用日志文件的一部分之前,
InnoDB将所有重做条目包含在该日志文件部分中的脏缓冲池页面刷新到磁盘上,这个过程称为
尖锐检查点。如果工作负载是写入密集型的,它会生成很多重做信息,全部写入日志文件。如果日志文件中的所有可用空间都用完,则会出现尖锐的检查点,导致吞吐量暂时下降。即使innodb_max_dirty_pages_pct没有达到这种情况也会发生
。
InnoDB通过测量缓冲池中脏页的数量和生成重做的速率,使用启发式算法来避免这种情况。根据这些数字,InnoDB决定每秒钟从缓冲池刷新多少脏页。这种自适应算法能够处理工作负载的突然变化。
内部基准测试表明,该算法不仅可以保持一段时间的吞吐量,还可以显着提高整体吞吐量。
由于自适应刷新可以显着影响工作负载的I / O模式,因此innodb_adaptive_flushing
可以使用
配置参数关闭此功能。innodb_adaptive_flushingis 的默认值
是
ON启用自适应刷新算法。您可以在MySQL选项文件(my.cnf或my.ini)中设置此参数的值,或者使用SET GLOBAL
需要SUPER特权的命令来动态更改它。
有关微调InnoDB
缓冲池刷新行为的信息,请参见第14.6.3.7节“微调InnoDB缓冲池刷新
”。
有关InnoDBI / O性能的更多信息,请参见第8.5.8节“优化InnoDB磁盘I / O”。
配置选项
innodb_flush_neighbors和
innodb_lru_scan_depth让你微调方面
冲洗的过程中
InnoDB
缓冲池。
这些选项主要有助于编写密集型 工作负载。如果DML活动很繁重 ,如果不够积极,刷新可能会落后,导致缓冲池中内存使用过多; 或者,由于刷新导致的磁盘写入可能会使您的I / O容量饱和,如果这种机制过于激进的话。理想的设置取决于您的工作负载,数据访问模式和存储配置(例如,数据是存储在HDD还是SSD设备上)。
对于工作负载较重的系统
或工作负载波动较大的系统,可以使用多个配置选项来微调表的刷新
行为InnoDB:
这些选项会导入选项使用的公式
innodb_adaptive_flushing
。
的innodb_adaptive_flushing,
innodb_io_capacity和
innodb_max_dirty_pages_pct
选项由以下选项限制或扩展:
该InnoDB
自适应冲洗
机制并不适合所有的情况。当重做日志
存在填满危险时,它提供了最大的好处。该
innodb_adaptive_flushing_lwm
选项指定重做日志容量的“ 低水位 ”百分比; 当超过该阈值时,
InnoDB即使未由innodb_adaptive_flushing
选项指定,也会启用自适应刷新
。
如果冲洗活动远远落后,InnoDB
可以冲洗比规定更积极
innodb_io_capacity。
innodb_io_capacity_max
表示在这种紧急情况下使用的I / O容量的上限,以便I / O中的峰值不会消耗服务器的所有容量。
InnoDB尝试从缓冲池中刷新数据,以便脏页面的百分比不超过值
innodb_max_dirty_pages_pct。默认值
innodb_max_dirty_pages_pct是75。
该
innodb_max_dirty_pages_pct
设置确定了冲洗活动的目标。它不会影响冲洗的速度。有关管理刷新速率的信息,请参见第14.6.3.6节“配置InnoDB缓冲池刷新
”。
该
innodb_max_dirty_pages_pct_lwm
选项指定一个“ 低水位 ”值,该值表示启用预先刷新以控制脏页比率并理想地防止脏页达到百分比的脏页的百分比
innodb_max_dirty_pages_pct。的值
innodb_max_dirty_pages_pct_lwm=0
禁用“ 冲洗前 ”行为。
上面提到的大多数选项最适用于长时间运行写入繁重工作负载的服务器,并且几乎没有减少加载时间以赶上等待写入磁盘的更改。
innodb_flushing_avg_loops
定义了InnoDB保持先前计算的刷新状态快照的迭代次数
,其控制自适应刷新响应前景负载变化的速度。设置较高的值
innodb_flushing_avg_loops意味着InnoDB保持之前计算的快照时间更长,所以自适应刷新响应速度更慢。较高的值也会减少前景和后台工作之间的正反馈,但设置较高值时,重要的是确保InnoDB重做日志利用率不会达到75%(异步刷新开始的硬编码限制),并且
innodb_max_dirty_pages_pct
设置可将脏页数保持在适合工作负载的级别。
具有一致工作负载的系统
innodb_log_file_size,大小不高的重做日志空间利用率达到75%的尖峰应使用较高的
innodb_flushing_avg_loops值,以尽可能保持平滑。对于极端负载峰值或日志文件不提供大量空间的系统,请考虑较小的
innodb_flushing_avg_loops
值。较小的值允许冲洗以紧密跟踪负载,并有助于避免达到75%的重做日志空间利用率。
为了减少重新启动服务器后的预热时间,请InnoDB在服务器关闭时为每个缓冲池保存最近使用的页面的百分比,并在服务器启动时恢复这些页面。存储的最近使用的页面的百分比由innodb_buffer_pool_dump_pct
配置选项定义
。
在重新启动繁忙的服务器后,通常会有一个预热期,吞吐量稳步增加,因为缓冲池中的磁盘页被带回到内存中(因为查询,更新了相同的数据)。在启动时恢复缓冲池的功能通过在重新启动之前重新加载缓冲池中的磁盘页而缩短了预热期,而不是等待DML操作访问相应的行。此外,I / O请求可以大批量执行,从而使整体I / O更快。页面加载发生在后台,并且不会延迟数据库启动。
除了在关闭时保存缓冲池状态并在启动时恢复缓冲池状态外,您还可以在服务器运行时随时保存和恢复缓冲池状态。例如,您可以在稳定的工作负载下达到稳定的吞吐量后保存缓冲池的状态。运行将数据页面带入缓冲池的报表或维护作业(仅针对这些操作请求)或运行其他非典型工作负载后,还可以恢复以前的缓冲池状态。
尽管一个缓冲池的大小可能是几千兆字节,但InnoDB通过比较,保存到磁盘的缓冲池数据很小。只有定位适当页面所需的表空间ID和页面ID才会保存到磁盘。该信息来自
表格。默认情况下,表空间ID和页面ID数据保存在名为的文件中,该文件
保存在
数据目录中。文件名和位置可以使用
配置参数进行修改
。
INNODB_BUFFER_PAGE_LRU
INFORMATION_SCHEMAib_buffer_poolInnoDBinnodb_buffer_pool_filename
由于数据与常规数据库操作一样,缓存在缓冲池中并且超出缓冲池,因此,如果最近更新了磁盘页面,或者如果DML操作涉及尚未加载的数据,则没有问题。加载机制跳过不存在的请求页面。
底层机制涉及调度执行转储和加载操作的后台线程。
压缩表中的磁盘页面以压缩格式加载到缓冲池中。在DML操作期间访问页面内容时,页面像往常一样解压缩。由于解压缩页面是CPU密集型进程,因此在连接线程中执行操作而不是执行缓冲池恢复操作的单个线程的并发性效率更高。
以下主题描述了与保存和恢复缓冲池状态相关的操作:
在从缓冲池中转储页面之前,可以通过设置innodb_buffer_pool_dump_pct
选项来配置要转储的最近使用的缓冲池页面的百分比
。如果您计划在服务器运行时转储缓冲池页面,则可以动态配置该选项:
SET GLOBAL innodb_buffer_pool_dump_pct = 40;
如果您计划在服务器关闭时转储缓冲池页面,请innodb_buffer_pool_dump_pct
在您的配置文件中进行设置
。
的[mysqld] innodb_buffer_pool_dump_pct = 40
该
innodb_buffer_pool_dump_pct
缺省值从100改为(转储所有页面)至25(转储最近最常使用的页面的25%)在MySQL 5.7的时候
innodb_buffer_pool_dump_at_shutdown
和
innodb_buffer_pool_load_at_startup
被默认启用。
要在关闭服务器时保存缓冲池的状态,请在关闭服务器之前发出以下语句:
SET GLOBAL innodb_buffer_pool_dump_at_shutdown = ON;
innodb_buffer_pool_dump_at_shutdown
是默认启用的。
要在服务器启动时恢复缓冲池状态,请在启动服务器时指定--innodb_buffer_pool_load_at_startup
选项:
mysqld --innodb_buffer_pool_load_at_startup = ON;
要在MySQL服务器运行时保存缓冲池的状态,请发出以下语句:
SET GLOBAL innodb_buffer_pool_dump_now = ON;
要在MySQL运行时恢复缓冲池状态,请发出以下语句:
SET GLOBAL innodb_buffer_pool_load_now = ON;
要将缓冲池状态保存到磁盘时显示进度,请发出以下语句:
SHOW STATUS LIKE'Innodb_buffer_pool_dump_status';
如果操作尚未开始,则返回“ 未开始 ”。如果操作完成,则打印完成时间(例如,完成时间为110505 12:18:02)。如果操作正在进行中,则提供状态信息(例如,转储缓冲池5/7,页面237/2873)。
要在加载缓冲池时显示进度,请发出以下语句:
SHOW STATUS LIKE'Innodb_buffer_pool_load_status';
如果操作尚未开始,则返回“ 未开始 ”。如果操作完成,则打印完成时间(例如,在110505 12:23:24完成)。如果操作正在进行中,则提供状态信息(例如,加载的123/22301页)。
您可以使用性能架构监视缓冲池负载进度 。
以下示例演示如何启用
stage/innodb/buffer pool loadstage事件工具和相关的使用者表以监视缓冲池加载进度。
有关此示例中使用的缓冲池转储和加载过程的信息,请参见 第14.6.3.8节“保存和恢复缓冲池状态”。有关Performance Schema阶段事件工具和相关使用者的信息,请参见 第25.11.5节“性能模式阶段事件表”。
启用stage/innodb/buffer pool
load仪器:
MySQL的>UPDATE performance_schema.setup_instruments SET ENABLED = 'YES'WHERE NAME LIKE 'stage/innodb/buffer%';
启用舞台活动消费表,其中包括
events_stages_current,
events_stages_history,和
events_stages_history_long。
MySQL的>UPDATE performance_schema.setup_consumers SET ENABLED = 'YES'WHERE NAME LIKE '%stages%';
通过启用转储当前缓冲池状态
innodb_buffer_pool_dump_now。
MySQL的> SET GLOBAL innodb_buffer_pool_dump_now=ON;
检查缓冲池转储状态以确保操作已完成。
MySQL的> SHOW STATUS LIKE 'Innodb_buffer_pool_dump_status'\G
*************************** 1. row ******************** *******
变量名称:Innodb_buffer_pool_dump_status
价值:缓冲池(s)转储完成在150202 16:38:58
通过启用加载缓冲池
innodb_buffer_pool_load_now:
MySQL的> SET GLOBAL innodb_buffer_pool_load_now=ON;
通过查询性能模式events_stages_current表来检查缓冲池加载操作的当前状态
。该WORK_COMPLETED列显示加载的缓冲池页面的数量。该
WORK_ESTIMATED列以页面形式提供了剩余工作的估计值。
MySQL的>SELECT EVENT_NAME, WORK_COMPLETED, WORK_ESTIMATEDFROM performance_schema.events_stages_current;+ ------------------------------- + ---------------- + ---------------- + | EVENT_NAME | WORK_COMPLETED | WORK_ESTIMATED | + ------------------------------- + ---------------- + ---------------- + | stage / innodb /缓冲池加载| 5353 | 7167 | + ------------------------------- + ---------------- + ---------------- +
events_stages_current
如果缓冲池加载操作完成,
该表将返回一个空集。在这种情况下,您可以检查
events_stages_history表格以查看已完成事件的数据。例如:
MySQL的>SELECT EVENT_NAME, WORK_COMPLETED, WORK_ESTIMATEDFROM performance_schema.events_stages_history;+ ------------------------------- + ---------------- + ---------------- + | EVENT_NAME | WORK_COMPLETED | WORK_ESTIMATED | + ------------------------------- + ---------------- + ---------------- + | stage / innodb /缓冲池加载| 7167 | 7167 | + ------------------------------- + ---------------- + ---------------- +
您也可以在启动时使用性能架构加载缓冲池时监控缓冲池负载进度
innodb_buffer_pool_load_at_startup。在这种情况下,stage/innodb/buffer pool
load必须在启动时启用仪器和相关使用者。有关更多信息,请参见
第25.3节“性能架构启动配置”。
InnoDB标准监视器输出可以使用
SHOW
ENGINE INNODB STATUS,提供与InnoDB缓冲池操作有关的度量。缓冲池度量标准位于标准监视器输出的BUFFER POOL AND
MEMORY部分,InnoDB并且类似于以下内容:
---------------------- 缓冲池和内存 ---------------------- 总大内存分配2198863872 分配了字典内存776332 缓冲池大小131072 空闲缓冲区124908 数据库页面5720 旧数据库页面2071 修改的数据页面910 等待读取0 等待写入:LRU 0,刷新列表0,单个页面0 年轻的4页,而不是年轻的0 0.10个年轻人/ s,0.00个非年轻人/ s 页面读取197,创建5523,写入5060 0.00读/秒,190.89创/秒,244.94写/秒 缓冲池命中率为1000/1000,年轻化率为0/1000 0/1000 提前读取的页数为0.00 / s,无需访问驱逐0.00 /秒,随机读取 前进0.00 /秒 LRU len:5720,unzip_LRU len:0 I / O sum [0]:cur [0],unzip sum [0]:cur [0]
下表介绍了InnoDB由InnoDB标准监视器报告的缓冲池度量标准。
InnoDB
标准监视器输出中
提供的每秒平均值基于自InnoDB上次打印标准监视器输出以来所用的时间
。
表14.2 InnoDB缓冲池度量标准
| 名称 | 描述 |
|---|---|
| 分配的内存总量 | 为缓冲池分配的总内存(以字节为单位)。 |
| 分配字典内存 | 为InnoDB数据字典分配的总内存(以字节为单位)。 |
| 缓冲池大小 | 分配给缓冲池的页面总大小。 |
| 免费缓冲区 | 缓冲池空闲列表的页面总大小。 |
| 数据库页面 | 缓冲池LRU列表的页面总大小。 |
| 旧的数据库页面 | 缓冲池旧LRU子列表的页面总大小。 |
| 修改数据库页面 | 当前在缓冲池中修改的页数。 |
| 等待读取 | 等待读入缓冲池的缓冲池页数。 |
| 等待写入LRU | 要从LRU列表底部写入的缓冲池中旧脏页的数量。 |
| 等待写入清单 | 在检查点中要刷新的缓冲池页面的数量。 |
| 等待写入单个页面 | 缓冲池中挂起的独立页面写入次数。 |
| 页面变得年轻 | 缓冲池LRU列表中的年轻页面总数(移至“ 新 ”页面的子列表头部)。 |
| 页面不是年轻的 | 在缓冲池LRU列表中没有变得年轻的页面总数(保留在“ 旧 ” 子列表中而没有变得年轻的页面)。 |
| 扬斯/秒 | 在缓冲池LRU列表中访问旧页面的平均每秒导致页面变得年轻。请参阅本表后面的注释以获取更多信息。 |
| 非杨氏/ s的 | 缓冲池LRU列表中旧页面的每秒平均访问量导致页面不够年轻。请参阅本表后面的注释以获取更多信息。 |
| 读取页面 | 从缓冲池中读取的总页数。 |
| 已创建页面 | 在缓冲池内创建的页面总数。 |
| 撰写的页面 | 从缓冲池写入的总页数。 |
| 读取/秒 | 每秒缓冲池页面读取的平均每秒数。 |
| 创建/秒 | 每秒创建的缓冲池页面的每秒平均数量。 |
| 写入/秒 | 每秒平均缓冲池页面写入次数。 |
| 缓冲池命中率 | 从缓冲池内存读取的页面的缓冲池页面命中率与磁盘存储的页面命中率。 |
| 年轻化率 | 页面访问的平均命中率导致页面变得年轻。请参阅本表后面的注释以获取更多信息。 |
| 不(年轻率) | 页面访问的平均点击率并未导致页面年轻化。请参阅本表后面的注释以获取更多信息。 |
| 预读页面 | 预读操作的每秒平均值。 |
| 被驱逐但无法访问的页面 | 被逐出的页面的平均每秒不从缓冲池访问。 |
| 随机预读 | 随机预读操作的每秒平均值。 |
| LRU len | 缓冲池LRU列表的页面总大小。 |
| unzip_LRU len | 缓冲池unzip_LRU列表的总页面大小。 |
| I / O总和 | 最近50秒访问的缓冲池LRU列表页面的总数。 |
| I / O当前 | 访问的缓冲池LRU列表页面的总数。 |
| I / O解压缩和 | 访问的缓冲池unzip_LRU列表页面的总数。 |
| I / O解压缩 | 访问的缓冲池unzip_LRU列表页面的总数。 |
备注:
该youngs/s指标只涉及旧页面。它基于对页面的访问次数而不是页数。可以对给定页面进行多次访问,所有这些都被计算在内。如果youngs/s在没有发生大扫描时看到非常低的
值,则可能需要缩短延迟时间或增加用于旧子列表的缓冲池的百分比。增加百分比会使旧的子列表变大,因此该子列表中的页面需要更长时间才能移动到尾部并被驱逐。这增加了页面被再次访问并变得年轻的可能性。
该non-youngs/s指标只涉及旧页面。它基于对页面的访问次数而不是页数。可以对给定页面进行多次访问,所有这些都被计算在内。如果non-youngs/s在进行大型表扫描(以及大量扫描youngs/s)时看不到很多,请增加延迟值。
该young-making率占访问到所有缓冲池页面,不只是访问旧子列表页面。的
young-making速度和
not速率通常不加起来的整体缓冲池命中率。页面在旧子列表中的命中会导致页面移动到新的子列表,但页面在新子列表中的命中会导致页面仅在与头部有一定距离时才移动到列表的头部。
not (young-making rate)是页面访问的平均命中率,由于innodb_old_blocks_time未达到定义的延迟,或者由于新子列表中的页面点击未导致页面移动到头部,所以页面访问的平均命中率未导致页面变得年轻
。此速率用于访问所有缓冲池页面,而不仅仅访问旧子列表中的页面。
InnoDB缓冲池
服务器状态变量,该
INNODB_BUFFER_POOL_STATS表提供了许多InnoDB标准监视器输出中找到的相同缓冲池指标
。有关该INNODB_BUFFER_POOL_STATS表的更多信息
,请参见
示例14.10,“查询INNODB_BUFFER_POOL_STATS表”。
在InnoDB开发时,随操作系统和运行时库提供的内存分配器往往缺乏性能和可扩展性。那时,没有为多核CPU调优的内存分配器库。因此,InnoDB在mem子系统中实现了自己的内存分配器。这个分配器由一个互斥体保护,这可能会成为一个
瓶颈。
InnoDB还在系统分配器(malloc和
free)周围实现了一个包装接口,同样由单个互斥体保护。
今天,随着多核系统变得越来越广泛,随着操作系统的成熟,在配备操作系统的内存分配器方面已经取得了重大进展。这些新的内存分配器执行得更好,比以往更具可扩展性。大多数工作负载,尤其是那些内存经常分配和释放的工作负载(如多表连接)可以使用高度调优的内存分配器而不是内部的
InnoDB特定内存分配器。
InnoDB通过innodb_use_sys_malloc在MySQL选项文件(my.cnf或
my.ini)中设置系统配置参数的值,
可以控制是使用其自己的内存分配器还是操作系统的分配器
。如果设置为ON或
1(默认),InnoDB使用malloc和free
,而不是底层系统的功能管理存储池本身。该参数不是动态的,只有在系统启动时才生效。要继续使用
InnoDB内存分配器,请设置
innodb_use_sys_malloc为
0。
当InnoDB内存分配器被禁用时,
InnoDB忽略参数的值
innodb_additional_mem_pool_size。该InnoDB内存分配器用来满足分配请求额外的内存池,而无需退回到系统内存分配器。当
InnoDB内存分配器被禁用时,所有这些分配请求都由系统内存分配器完成。
在使用动态链接的类Unix系统上,替换内存分配器可能与创建环境变量LD_PRELOAD或
LD_LIBRARY_PATH指向实现分配器的动态库一样简单
。在其他系统上,可能需要重新链接。请参阅您选择的内存分配程序库的文档。
由于InnoDB在使用系统内存分配程序(innodb_use_sys_mallocis
ON)时无法跟踪所有内存使用情况,因此命令输出中的“ BUFFER POOL AND MEMORY ”部分SHOW ENGINE INNODB
STATUS仅包含“已分配总内存 ”中的缓冲池统计信息。任何使用mem子系统或使用
分配的内存都将ut_malloc被排除。
innodb_use_sys_malloc并
innodb_additional_mem_pool_size
在MySQL 5.6中被弃用,并在MySQL 5.7中被删除。
有关InnoDB内存使用情况对性能影响的更多信息
,请参见
第8.10节“缓冲和高速缓存”。
时INSERT,
UPDATE和
DELETE操作是在一个表来执行,索引列的值(辅助键的特别的值)在未排序的顺序常常是,需要大量的I / O以使辅助索引是最新的。
InnoDB有一个
更改缓冲区,用于在相关页面不在
缓冲池中时将更改缓存到辅助索引条目
,从而避免通过从磁盘立即读取页面而导致的昂贵的I / O操作。缓存的更改在页面加载到缓冲池时合并,并且更新的页面稍后刷新到磁盘。该InnoDB主线程在服务器几乎空闲时以及缓慢关闭期间合并缓存的更改
。
因为它可能导致更少的磁盘读取和写入操作,所以对于I / O绑定的工作负载,更改缓冲区功能是最有价值的,例如具有大量DML操作(如批量插入)的应用程序。
但是,更改缓冲区占用了缓冲池的一部分,减少了可用于缓存数据页的内存。如果工作集几乎适合缓冲池,或者如果您的表具有相对较少的二级索引,则禁用更改缓冲可能会很有用。如果工作集完全适合缓冲区,更改缓冲不会带来额外的开销,因为它仅适用于不在缓冲池中的页。
您可以InnoDB
使用innodb_change_buffering
配置参数控制执行更改缓冲
的范围。您可以启用或禁用缓冲插入,删除操作(索引记录最初标记为删除时)和清除操作(索引记录物理删除时)。更新操作是插入和删除的组合。默认
innodb_change_buffering值是
all。
允许的innodb_change_buffering
值包括:
all
默认值:缓冲区插入,删除标记操作和清除。
none
不要缓冲任何操作。
inserts
缓冲区插入操作。
deletes
缓冲区删除标记操作。
changes
缓冲插入和删除标记操作。
purges
缓冲在后台发生的物理删除操作。
您可以innodb_change_buffering在MySQL选项文件(my.cnf或
my.ini)中设置
参数,或者使用SET GLOBAL
需要SUPER特权的命令动态更改它
。更改设置会影响新操作的缓冲; 现有缓冲条目的合并不受影响。
有关相关信息,请参见 第14.4.2节“更改缓冲区”。有关配置更改缓冲区大小的信息,请参见 第14.6.5.1节“配置更改缓冲区的最大大小”。
从MySQL 5.6.2开始,使用
innodb_change_buffer_max_size
配置选项可以将更改缓冲区的最大大小配置为缓冲池总大小的百分比。默认情况下,
innodb_change_buffer_max_size
设置为25.最大设置为50。
您可能会考虑innodb_change_buffer_max_size
在MySQL服务器上增加
大量插入,更新和删除活动,其中更改缓冲区合并跟不上新的更改缓冲区条目,导致更改缓冲区达到其最大大小限制。
您可能会考虑innodb_change_buffer_max_size
使用用于报告的静态数据在MySQL服务器上减少
数据量,或者如果更改缓冲区消耗的内存空间与缓冲池共享的空间过多,则会导致页面比期望的更早退出缓冲池。
使用代表性工作负载测试不同的设置以确定最佳配置。该
innodb_change_buffer_max_size
设置是动态的,可以在不重新启动服务器的情况下修改设置。
InnoDB使用操作系统
线程处理来自用户事务的请求。(事务InnoDB在提交或回滚之前可能会发出很多请求
。)在具有多核处理器的现代操作系统和服务器上,在上下文切换有效的情况下,大多数工作负载运行良好,对并发线程数没有任何限制。MySQL 5.5及以上版本的可伸缩性改进降低了对内部并发执行线程数量的限制
InnoDB。
在线程之间的上下文切换最小化的情况下,InnoDB可以使用许多技术来限制并发执行的操作系统线程的数量(并且因此限制任何时候处理的请求的数量)。当InnoDB从用户会话接收到新请求时,如果并发执行的线程数量处于预定义的限制,则新请求会在短时间内休眠,然后再次尝试。睡眠之后无法重新安排的请求被放入先入先出队列中并最终被处理。等待锁的线程不计入并发执行线程的数量。
您可以通过设置配置参数来限制并发线程的数量
innodb_thread_concurrency。一旦执行线程的数量达到此限制,其他线程innodb_thread_sleep_delay在被放入队列之前会睡眠数微秒(由配置参数
设置)。
以前,它需要进行实验才能找到最佳值innodb_thread_sleep_delay,并且最佳值可能会根据工作负载而改变。在MySQL 5.6.3及更高版本中,可以将配置选项设置为
innodb_adaptive_max_sleep_delay
允许的最高值
innodb_thread_sleep_delay,并
根据当前的线程调度活动InnoDB自动调整
innodb_thread_sleep_delay向上或向下。这种动态调整有助于线程调度机制在系统轻载时以及接近满负载运行时顺利运行。
innodb_thread_concurrency并发线程数
的默认值
和默认的并发线程数默认限制在各种版本的MySQL和
InnoDB。innodb_thread_concurrencyis 的默认值
是
0,所以默认情况下并发执行线程的数量没有限制。
InnoDB只有当并发线程数量有限时,才会使线程进入睡眠状态。在线程数没有限制的情况下,所有的竞争都是预定的。也就是说,如果innodb_thread_concurrency
是0,那么值
innodb_thread_sleep_delay被忽略。
当线程数有限制时(当
innodb_thread_concurrency> 0时),InnoDB通过允许在执行单个SQL语句期间进行的多个请求进入InnoDB而不遵守设置的限制
来
减少上下文切换开销
innodb_thread_concurrency。由于SQL语句(如连接)可能包含多个行操作InnoDB,因此
InnoDB会分配指定数量的
“ 票据 ”,以便以最小的开销重复调度线程。
当一个新的SQL语句启动时,一个线程没有票据,并且必须遵守
innodb_thread_concurrency。一旦线程有权输入InnoDB,它将被分配一些门票,它可以用于随后进入InnoDB执行行操作。如果票据用完,线程被驱逐,并且
innodb_thread_concurrency再次被观察到,这可能使线程回到等待线程的先进/先出队列中。当线程再次有资格输入时InnoDB,门票再次分配。分配的票数由全局选项指定
innodb_concurrency_tickets,默认为5000。一旦锁定可用,正在等待锁定的线程将被授予一张票。
这些变量的正确值取决于您的环境和工作负载。尝试一系列不同的值来确定适用于您的应用程序的值。在限制并发执行线程的数量之前,请查看可以提高InnoDB多核和多处理器计算机性能的配置选项,例如
innodb_adaptive_hash_index。
有关MySQL线程处理的一般性能信息,请参见第8.12.5.1节“MySQL如何使用线程进行客户端连接”。
InnoDB使用后台
线程来处理各种类型的I / O请求。您可以使用innodb_read_io_threads和
innodb_write_io_threads
配置参数配置服务在数据页上读写I / O的后台线程
数。这些参数分别表示用于读取和写入请求的后台线程的数量。它们在所有支持的平台上都很有效。您可以在MySQL选项文件(my.cnf或my.ini)中为这些参数设置值; 你不能动态改变数值。这些参数的默认值是4和允许值范围从1-64。
这些配置选项的目的是为了InnoDB在高端系统上实现
更高的可扩展性。每个后台线程最多可处理256个待处理的I / O请求。后台I / O的主要来源是
预读请求。
InnoDB试图以大多数后台线程平等共享工作的方式平衡传入请求的负载。InnoDB还会尝试将同一范围内的读取请求分配给相同的线程,以增加合并请求的机会。如果您有高端I / O子系统,并且innodb_read_io_threads在SHOW ENGINE INNODB STATUS
输出中看到超过64个
未决读取请求,则可以通过增加值来提高性能
innodb_read_io_threads。
在Linux系统上,InnoDB默认情况下使用异步I / O子系统来执行数据文件页面的预读和写请求,这会改变
InnoDB后台线程处理这些类型的I / O请求的方式。有关更多信息,请参见
第14.6.8节“在Linux上使用异步I / O”。
有关InnoDBI / O性能的更多信息,请参见第8.5.8节“优化InnoDB磁盘I / O”。
InnoDB在Linux上使用异步I / O子系统(本机AIO)来执行数据文件页的预读和写请求。此行为由innodb_use_native_aio
配置选项控制,该选项仅适用于Linux系统,默认情况下处于
启用状态。在其他类Unix系统上,只
InnoDB使用同步I / O。历史上,
InnoDB只在Windows系统上使用异步I / O。在Linux上使用异步I / O子系统需要该libaio库。
通过同步I / O,查询线程对I / O请求InnoDB进行排队,
后台线程一次检索一个排队请求,为每个请求发出一个同步I / O调用。当I / O请求完成且I / O调用返回时,InnoDB处理请求的
后台线程调用I / O完成例程并返回以处理下一个请求。可以并行处理的请求数是n,后台线程n的数量
在哪里
InnoDB。InnoDB后台线程的数量
由innodb_read_io_threads和
控制
innodb_write_io_threads。请参见
第14.6.7节“配置背景InnoDB I / O线程数”。
使用本机AIO,查询线程直接向操作系统发送I / O请求,从而消除后台线程数量所带来的限制。InnoDB后台线程等待I / O事件来表示已完成的请求。当请求完成时,后台线程调用I / O完成例程并继续等待I / O事件。
本机AIO的优势在于,对于I / O受限的系统来说,可扩展性通常会在SHOW ENGINE INNODB STATUS\G输出中显示许多未决的读取/写入操作
。使用本机AIO时并行处理的增加意味着I / O调度程序的类型或磁盘阵列控制器的属性对I / O性能有更大的影响。
本机AIO对于I / O密集型系统的潜在缺点是缺乏对同时分派给操作系统的I / O写入请求数量的控制。根据I / O活动的数量和系统功能的不同,调度到操作系统进行并行处理的太多I / O写请求可能会导致I / O读取不足。
如果操作系统中的异步I / O子系统的问题阻止InnoDB启动,则可以使用启动服务器
innodb_use_native_aio=0。如果InnoDB检测到潜在问题(例如tmpdir位置,
tmpfs文件系统和不支持异步I / O的Linux内核组合),则也可能在启动过程中自动禁用此选项
tmpfs。
InnoDB中 的主线程是一个在后台执行各种任务的线程。这些任务中的大多数都与I / O相关,例如从缓冲池中清除脏页或将插入缓冲区中的更改写入适当的二级索引。主线程尝试以不会对服务器的正常工作产生不利影响的方式执行这些任务。它试图估计可用的空闲I / O带宽,并调整其活动以利用此免费容量。历史上,InnoDB使用了100 IOP(每秒输入/输出操作)的硬编码值作为服务器的总I / O容量。
该参数innodb_io_capacity
表示InnoDB可用的整体I / O容量。此参数应设置为大约系统每秒可执行的I / O操作的数量。该值取决于您的系统配置。何时
innodb_io_capacity设置,主线程根据设置值估计可用于后台任务的I / O带宽。设置该值以
100恢复到旧的行为。
您可以将值设置
innodb_io_capacity为任何数字100或更大。默认值是200,反映了典型的现代I / O设备的性能比MySQL早期的性能更高。通常,以前的默认值100左右的值适用于消费级存储设备,例如高达7200 RPM的硬盘驱动器。更快的硬盘驱动器,RAID配置和固态硬盘从更高的价值中受益。
该innodb_io_capacity设置是所有缓冲池实例的总限制。当刷新脏页时,innodb_io_capacity
限制在缓冲池实例中平均分配。有关更多信息,请参阅
innodb_io_capacity系统变量说明。
您可以在MySQL选项文件(my.cnf或my.ini)中设置此参数的值,或者使用SET GLOBAL需要SUPER特权的命令来动态更改它。
的innodb_flush_sync
配置选项使
innodb_io_capacity发生在检查点I / O活动的脉冲串期间被忽略设置。
innodb_flush_sync是默认启用的。
以前,InnoDB主线程还执行任何所需的清除
操作。在MySQL 5.6.5及更高版本中,这些I / O操作将移动到其他后台线程,后台线程的编号由innodb_purge_threads
配置选项控制。
有关InnoDB I / O性能的更多信息,请参见 第8.5.8节“优化InnoDB磁盘I / O”。
很多InnoDB 互斥锁和 rw锁都保留了很短时间。在多核系统上,线程可以更有效地检查睡眠前是否可以获取互斥锁或rw锁。如果在此轮询期间互斥锁或rw锁可用,则线程可以在同一时间片内立即继续。然而,由多个共享对象线程轮询太频繁会导致“ 缓存乒乓 ”,不同的处理器会使每个其他缓存的部分无效。InnoDB通过在随后的轮询之间等待随机时间来最小化这个问题。延迟被实现为繁忙循环。
您可以使用参数控制测试互斥锁或rw锁之间的最大延迟时间
innodb_spin_wait_delay。延迟循环的持续时间取决于C编译器和目标处理器。(在100MHz奔腾时代,延迟单位是1微秒)。在所有处理器内核共享快速高速缓存的系统上,您可以通过设置来减少最大延迟或完全禁用忙碌循环
innodb_spin_wait_delay=0。在具有多个处理器芯片的系统上,高速缓存失效的影响可能更为显着,您可能会增加最大延迟。
innodb_spin_wait_delayis
的默认值
6。旋转等待延迟是一个动态的全局参数,您可以在MySQL选项文件(my.cnf或my.ini)中指定,或者在运行时使用该命令进行更改,其中是所需的最大延迟。更改设置需要
特权。
SET GLOBAL
innodb_spin_wait_delay=delaydelaySUPER
有关InnoDB锁定操作的性能注意事项,请参见 第8.11节“优化锁定操作”。
InnoDB自动执行 的清除操作(一种垃圾收集)可以由一个或多个单独的线程执行,而不是作为主线程的一部分。通过允许主数据库操作独立于后台发生的维护工作,独立线程的使用提高了可伸缩性。
要控制此功能,请增加配置选项的值innodb_purge_threads。如果DML操作集中在单个表或几个表上,请将设置保持为低,以便线程不会彼此竞争访问繁忙表。如果DML操作分散在多个表中,请增加设置。它的最大值是32.
innodb_purge_threads是一个非动态配置选项,这意味着它不能在运行时配置。
还有另一个相关配置选项,
innodb_purge_batch_size默认值为300,最大值为5000.此选项主要用于试验和调整清除操作,对典型用户应该不感兴趣。
有关InnoDB I / O性能的更多信息,请参见 第8.5.8节“优化InnoDB磁盘I / O”。
本节介绍如何为表配置持久性和非持久性优化器统计信息InnoDB
。
持久性优化器统计信息在服务器重新启动时保持不变,从而实现更高的 计划稳定性和更一致的查询性能。持久优化器统计数据还提供了控制和灵活性以及这些额外的好处:
您可以使用
innodb_stats_auto_recalc
配置选项来控制是否在对表格进行实质性更改后自动更新统计信息。
您可以使用STATS_PERSISTENT,
STATS_AUTO_RECALC以及
STATS_SAMPLE_PAGES与条款
CREATE TABLE和
ALTER TABLE声明配置个别表优化统计。
您可以查询mysql.innodb_table_stats和
mysql.innodb_index_stats表中的优化器统计数据
。
您可以查看和
表格的last_update列
以查看统计信息上次更新的时间。
mysql.innodb_table_statsmysql.innodb_index_stats
您可以手动修改
mysql.innodb_table_stats和
mysql.innodb_index_stats表来强制执行特定的查询优化计划,或者在不修改数据库的情况下测试替代计划。
持久优化器统计信息功能默认为启用(innodb_stats_persistent=ON)。
在每次服务器重启时以及在其他操作之后清除非永久性优化器统计信息,并在下一次表访问时重新计算。因此,重新计算统计信息时可能会产生不同的估计值,从而导致执行计划的不同选择和查询性能的变化。
本节还提供了有关估计ANALYZE TABLE复杂性的信息
,这在尝试实现精确统计和ANALYZE TABLE
执行时间之间的平衡时可能会有用。
持久化优化器统计功能通过将统计数据存储到磁盘并使其在服务器重新启动时保持不变,从而提高 计划稳定性,从而 优化器每次对给定查询更可能做出一致的选择。
innodb_stats_persistent=ON当创建或更改单个表
时,优化程序统计信息会保存到磁盘
STATS_PERSISTENT=1。
innodb_stats_persistent是默认启用的。
以前,优化器统计信息在每次服务器重启时以及其他一些操作之后都被清除,并在下一次表访问时重新计算。因此,重新计算统计信息时可能会产生不同的估计值,导致查询执行计划中的选择不同,从而导致查询性能发生变化。
如第14.6.12.1.5节“InnoDB持久统计表”
中所述mysql.innodb_table_stats,持久性统计信息存储在
和
mysql.innodb_index_stats表中。
要恢复使用非持久性优化器统计信息,可以使用
语句修改表。有关相关信息,请参见
第14.6.12.2节“配置非持久性优化器统计参数”ALTER TABLE
tbl_name STATS_PERSISTENT=0
innodb_stats_auto_recalc
缺省情况下启用
的配置选项确定当表经历实质性更改(超过10%的行)时是否自动计算统计信息。您还可以使用STATS_AUTO_RECALCa CREATE TABLE或
ALTER TABLE语句中的子句
为单个表配置自动统计信息重新计算
。
innodb_stats_auto_recalc是默认启用的。
由于自动统计信息重新计算(发生在后台)的异步性质,即使innodb_stats_auto_recalc启用了运行影响超过10%表格的DML操作,统计信息也可能不会立即重新计算
。在某些情况下,统计数据重新计算可能会延迟几秒钟。如果在更改表的重要部分后立即需要最新的统计信息,请运行ANALYZE TABLE以启动统计信息的同步(前台)重新计算。
如果innodb_stats_auto_recalc
禁用,请在ANALYZE TABLE
对索引列进行重大更改后,通过为每个适用的表发布语句来确保优化程序统计信息的准确性。代表性数据加载到表中后,您可以在设置脚本中运行此语句,并且在DML操作显着更改索引列的内容之后定期运行此语句,或者在活动较少时按计划运行。将新索引添加到现有表格时,索引统计信息将被计算并添加到innodb_index_stats表格中,而不考虑其值
innodb_stats_auto_recalc。
要确保
在创建新索引时收集统计信息,请启用该
innodb_stats_auto_recalc
选项,或者ANALYZE TABLE在启用持久统计信息模式时创建每个新索引后运行。
innodb_stats_persistent,
innodb_stats_auto_recalc并且
innodb_stats_persistent_sample_pages
是全局配置选项。要覆盖这些系统的设置和配置单个表优化统计参数,你可以定义
STATS_PERSISTENT,
STATS_AUTO_RECALC和
STATS_SAMPLE_PAGES子句
CREATE TABLE或
ALTER TABLE语句。
STATS_PERSISTENT指定是否启用
持续统计为一个InnoDB表。该值DEFAULT导致表的持久统计信息设置由innodb_stats_persistent
配置选项确定
。该值为1
表启用持久性统计信息,而值0会关闭此功能。在通过a CREATE
TABLE或ALTER TABLE
语句启用持久性统计ANALYZE
TABLE信息后,在将代表性数据加载到表中之后,发出语句来计算统计信息。
STATS_AUTO_RECALC指定是否自动重新计算
持续的统计数据为InnoDB表。该值DEFAULT导致表的持久统计信息设置由innodb_stats_auto_recalc
配置选项确定
。该值1
导致统计信息在表中数据的10%已更改时重新计算。该值0
可防止对此表进行自动重新计算; 在此设置下,ANALYZE
TABLE在对表格进行重大更改后,发布重新计算统计数据的声明。
STATS_SAMPLE_PAGES指定估算索引列的基数和其他统计数据时要采样的索引页数,例如由ANALYZE
TABLE。
以下CREATE TABLE示例中指定了所有三个子句
:
CREATE TABLE`t1`( `id` int(8)NOT NULL auto_increment, `data` varchar(255), `日期`日期时间, PRIMARY KEY(`id`), INDEX`DATE_IX`(`日期`) )ENGINE = InnoDB, STATS_PERSISTENT = 1, STATS_AUTO_RECALC = 1, STATS_SAMPLE_PAGES = 25;
MySQL查询优化器使用关于密钥分发的估计
统计信息来根据索引的相对选择性来选择执行计划
的索引。诸如ANALYZE
TABLE原因之类的操作InnoDB从表格上的每个索引对随机页面进行采样以估计索引的
基数。(这种技术被称为
随机潜水。)
为了使您能够控制统计估计的质量(从而为查询优化器提供更好的信息),可以使用innodb_stats_persistent_sample_pages可以在运行时设置的参数来更改采样页面的数量
。
innodb_stats_persistent_sample_pages
默认值为20.作为一般准则,请在遇到以下问题时考虑修改此参数:
统计信息不够准确,优化程序选择次优计划,如EXPLAIN输出所示
。统计的准确性可以通过比较索引的实际基数(通过SELECT
DISTINCT在索引列上运行返回
)与mysql.innodb_index_stats持久统计表中提供的估计值来检查
。
如果确定统计数据不够准确,innodb_stats_persistent_sample_pages
则应增加数值,
直到统计数据估计足够精确。innodb_stats_persistent_sample_pages
然而,增加
太多会导致
ANALYZE TABLE缓慢运行。
ANALYZE TABLE太慢了。在这种情况下
innodb_stats_persistent_sample_pages
应该减少,直到ANALYZE
TABLE执行时间可以接受。但是,如果将价值降低太多,可能会导致统计数据不准确和次优查询执行计划的第一个问题。
如果在准确的统计信息和ANALYZE
TABLE执行时间之间无法实现平衡,请考虑减少表中索引列的数量或限制分区数量以降低
ANALYZE TABLE复杂性。因为主键列被附加到每个非唯一索引,所以表的主键列数也很重要。
有关相关信息,请参见 第14.6.12.3节“估计InnoDB表的ANALYZE TABLE复杂度”。
默认情况下,InnoDB在计算统计信息时读取未提交的数据。如果未提交的事务从表中删除行,则
InnoDB排除在计算行估计和索引统计信息时删除标记的记录,这可能会导致针对在表上操作的其他事务的非最佳执行计划使用事务隔离级别以外的
READ UNCOMMITTED。为了避免这种情况,
innodb_stats_include_delete_marked
可以启用它来确保InnoDB
在计算持久性优化器统计信息时包含删除标记的记录。
当
innodb_stats_include_delete_marked
启用时,ANALYZE TABLE
重新计算统计数据时,会考虑删除标记的记录。
innodb_stats_include_delete_marked
是影响所有InnoDB
表的全局设置,并且仅适用于持久性优化器统计信息。
innodb_stats_include_delete_marked
在MySQL 5.7.16中引入。
持久性统计信息功能依赖于mysql数据库中的内部管理表,名为
innodb_table_statsand
innodb_index_stats。这些表格在所有安装,升级和源代码构建过程中自动设置。
表14.3 innodb_table_stats的列
| 列名称 | 描述 |
|---|---|
database_name |
数据库名称 |
table_name |
表名称,分区名称或子分区名称 |
last_update |
指示上次InnoDB
更新此行的时间戳 |
n_rows |
表中的行数 |
clustered_index_size |
主索引的大小,以页为单位 |
sum_of_other_index_sizes |
其他(非主要)索引的总大小,以页为单位 |
表14.4 innodb_index_stats的列
| 列名称 | 描述 |
|---|---|
database_name |
数据库名称 |
table_name |
表名称,分区名称或子分区名称 |
index_name |
索引名称 |
last_update |
指示上次InnoDB
更新此行的时间戳 |
stat_name |
统计的名称,其值在stat_value列中报告
|
stat_value |
stat_name
列中命名的统计值的值 |
sample_size |
为stat_value列中提供的估算抽样的页数
|
stat_description |
在stat_name列中命名的统计信息的描述
|
无论是innodb_table_stats和
innodb_index_stats表包括一个
last_update示出了当柱
InnoDB最后更新索引的统计,如显示在下面的例子:
MySQL的> SELECT * FROM innodb_table_stats \G
*************************** 1. row ******************** *******
database_name:sakila
table_name:actor
last_update:2014-05-28 16:16:44
n_rows:200
clustered_index_size:1
sum_of_other_index_sizes:1
...MySQL的> SELECT * FROM innodb_index_stats \G
*************************** 1. row ******************** *******
database_name:sakila
table_name:actor
index_name:PRIMARY
last_update:2014-05-28 16:16:44
stat_name:n_diff_pfx01
stat_value:200
sample_size:1
...
在innodb_table_stats和
innodb_index_stats表是普通表,可以手动更新。通过手动更新统计信息的功能,可以强制执行特定的查询优化计划或测试备选计划,而无需修改数据库。如果您手动更新统计信息,请发出命令让MySQL重新载入更新后的统计信息。
FLUSH TABLE
tbl_name
持久性统计信息被认为是本地信息,因为它们与服务器实例有关。在
innodb_table_stats与
innodb_index_stats表时自动重新计算统计发生,因此不复制。如果运行ANALYZE TABLE
以启动统计信息的同步重新计算,则会复制此语句(除非您禁止对其进行日志记录),并且重新计算将发生在复制从服务器上。
该innodb_table_stats表格每个表格包含一行。收集的数据将在以下示例中演示。
表t1含有伯指数(列
a,b)二级索引(列c,d),和唯一索引(列e,
f):
CREATE TABLE t1( a INT,b INT,c INT,d INT,e INT,f INT, PRIMARY KEY(a,b),KEY i1(c,d),UNIQUE KEY i2uniq(e,f) )ENGINE = INNODB;
插入五行样本数据后,表格如下所示:
MySQL的> SELECT * FROM t1;
+ --- + --- + ------ + ------ + ------ + ------ +
| a | b | c | d | e | f |
+ --- + --- + ------ + ------ + ------ + ------ +
| 1 | 1 | 10 | 11 | 100 | 101 |
| 1 | 2 | 10 | 11 | 200 | 102 |
| 1 | 3 | 10 | 11 | 100 | 103 |
| 1 | 4 | 10 | 12 | 200 | 104 |
| 1 | 5 | 10 | 12 | 100 | 105 |
+ --- + --- + ------ + ------ + ------ + ------ +
要立即更新统计信息,请运行ANALYZE TABLE(如果
innodb_stats_auto_recalc已启用,假设已达到更改的表行的10%阈值,则会在几秒钟内自动更新统计信息
):
MySQL的> ANALYZE TABLE t1;
+ --------- + --------- + ---------- + ---------- +
| 表| 操作| Msg_type | Msg_text |
+ --------- + --------- + ---------- + ---------- +
| test.t1 | 分析| 状态| 好的|
+ --------- + --------- + ---------- + ---------- +
表中的表统计信息t1显示上次InnoDB更新表统计信息(2014-03-14 14:36:34),表()中的行数5,聚集索引大小(1页面)以及其他索引(2页面)的组合大小。
MySQL的> SELECT * FROM mysql.innodb_table_stats WHERE table_name like 't1'\G
*************************** 1. row ******************** *******
database_name:test
table_name:t1
last_update:2014-03-14 14:36:34
n_rows:5
clustered_index_size:1
sum_of_other_index_sizes:2
该innodb_index_stats表包含每个索引的多行。innodb_index_stats表格中的每一行都提供与列中
所列名称和stat_name列中所述
的特定索引统计信息相关的数据
stat_description。例如:
MySQL的>SELECT index_name, stat_name, stat_value, stat_descriptionFROM mysql.innodb_index_stats WHERE table_name like 't1';+ ------------ + -------------- + ------------ + -------- --------------------------- + | index_name | stat_name | stat_value | stat_description | + ------------ + -------------- + ------------ + -------- --------------------------- + | PRIMARY | n_diff_pfx01 | 1 | a | | PRIMARY | n_diff_pfx02 | 5 | a,b | | PRIMARY | n_leaf_pages | 1 | 索引|中的叶子页数 | PRIMARY | 大小| 1 | 索引中的页数| | i1 | n_diff_pfx01 | 1 | c | | i1 | n_diff_pfx02 | 2 | c,d | | i1 | n_diff_pfx03 | 2 | c,d,a | | i1 | n_diff_pfx04 | 5 | c,d,a,b | | i1 | n_leaf_pages | 1 | 索引|中的叶子页数 | i1 | 大小| 1 | 索引中的页数| | i2uniq | n_diff_pfx01 | 2 | e | | i2uniq | n_diff_pfx02 | 5 | e,f | | i2uniq | n_leaf_pages | 1 | 索引|中的叶子页数 | i2uniq | 大小| 1 | 索引中的页数| + ------------ + -------------- + ------------ + -------- --------------------------- +
该stat_name列显示以下类型的统计信息:
size:Where
stat_name= size,
stat_value列显示索引中的页面总数。
n_leaf_pages:Where
stat_name= n_leaf_pages,stat_value列显示索引中叶页的数量。
n_diff_pfx:Where
NNstat_name= n_diff_pfx01,stat_value列显示索引第一列中不同值的数量。Where
stat_name= n_diff_pfx02,该stat_value列显示索引前两列中不同值的数量,以此类推。此外,where
stat_name= ,该列显示了一个以逗号分隔的被计数的索引列表。
n_diff_pfxNNstat_description
为了进一步说明
提供基数数据的
统计量,再次考虑先前引入的表格示例。如下所示,该
表是用主索引(列而创建,),辅指数(列,
),和唯一索引(列
,):
n_diff_pfxNNt1t1abcdef
CREATE TABLE t1( a INT,b INT,c INT,d INT,e INT,f INT, PRIMARY KEY(a,b),KEY i1(c,d),UNIQUE KEY i2uniq(e,f) )ENGINE = INNODB;
插入五行样本数据后,表格如下所示:
MySQL的> SELECT * FROM t1;
+ --- + --- + ------ + ------ + ------ + ------ +
| a | b | c | d | e | f |
+ --- + --- + ------ + ------ + ------ + ------ +
| 1 | 1 | 10 | 11 | 100 | 101 |
| 1 | 2 | 10 | 11 | 200 | 102 |
| 1 | 3 | 10 | 11 | 100 | 103 |
| 1 | 4 | 10 | 12 | 200 | 104 |
| 1 | 5 | 10 | 12 | 100 | 105 |
+ --- + --- + ------ + ------ + ------ + ------ +
当您查询index_name,
stat_name,stat_value,和stat_description在那里
stat_name LIKE 'n_diff%',下面的返回结果集:
MySQL的>SELECT index_name, stat_name, stat_value, stat_descriptionFROM mysql.innodb_index_statsWHERE table_name like 't1' AND stat_name LIKE 'n_diff%';+ ------------ + -------------- + ------------ + -------- ---------- + | index_name | stat_name | stat_value | stat_description | + ------------ + -------------- + ------------ + -------- ---------- + | PRIMARY | n_diff_pfx01 | 1 | a | | PRIMARY | n_diff_pfx02 | 5 | a,b | | i1 | n_diff_pfx01 | 1 | c | | i1 | n_diff_pfx02 | 2 | c,d | | i1 | n_diff_pfx03 | 2 | c,d,a | | i1 | n_diff_pfx04 | 5 | c,d,a,b | | i2uniq | n_diff_pfx01 | 2 | e | | i2uniq | n_diff_pfx02 | 5 | e,f | + ------------ + -------------- + ------------ + -------- ---------- +
对于PRIMARY索引,有两
n_diff%行。行数等于索引中的列数。
对于非唯一索引,InnoDB附加主键的列。
其中
index_name= PRIMARY
和
stat_name= n_diff_pfx01,的stat_value是1,这表明存在于索引(列的第一列的单个独特的值
a)。列中的不同值的数量a通过查看a表中的列中
的数据来确认t1,其中存在单个不同的值(1)。计数的列(a)显示在stat_description结果集的
列中。
where
index_name= PRIMARY
and
stat_name= n_diff_pfx02,stat_valueis 5,表示索引(a,b)的两列中有五个不同的值。的不同值的列数a
和b通过查看在列中的数据证实a和b
在表t1,其中有五个不同的值:( ),(1,1),(1,2 1,3),(1,4和)( 1,5)。计数的列(a,b)显示在stat_description结果集的
列中。
对于二级索引(i1),有n_diff%四行。只为辅助索引(c,d)定义了两列,但辅助索引有n_diff%四行,因为InnoDB所有非唯一索引都带有主键后缀。因此,有n_diff%四行而不是两个来说明二级索引列(c,d)和主键列(a,b)。
其中index_name= i1
和
stat_name= n_diff_pfx01,的stat_value是1,这表明存在于索引(列的第一列的单个独特的值
c)。列中的不同值的数量c通过查看c表中的列中
的数据来确认t1,其中存在单个不同的值:(10)。计数的列(c)显示在stat_description结果集的
列中。
其中index_name= i1
和
stat_name= n_diff_pfx02,stat_valueis 2,它表示索引(c,d)的前两列中有两个不同的值。通过查看列和
表中的数据来确认列can中的不同值的数量
,其中有两个不同的值:()和()。计数的列()显示在结果集的列中。
dcdt110,1110,12c,dstat_description
其中index_name= i1
和
stat_name= n_diff_pfx03,stat_valueis 2,它表示索引(c,d,a)的前三列中有两个不同的值。不同的值的列的数量c,d以及
a由列查看数据证实c,d和
a在表t1,其中有两个不同的值:( 10,11,1)和(10,12,1)。计数的列(c,d,a)显示在stat_description结果集的
列中。
其中index_name= i1
和
stat_name= n_diff_pfx04,stat_valueis 5,它表示索引(c,d,a,b)的四列中有五个不同的值。不同的值的列的数量
c,d,
a并且b是通过在列查看数据证实c,
d,a,和
b在表t1,其中有五个不同的值:( ),(10,11,1,1),(10,11,1,2),(10,11,1,3 10,12,1,4)和(10,12,1,5)。计数的列(c,d,a,b)显示在stat_description结果集的
列中。
对于唯一索引(i2uniq),有两n_diff%行。
其中
index_name= i2uniq
和
stat_name= n_diff_pfx01,stat_valueis 2,表示索引(列e)的第一列中有两个不同的值。列中的不同值的数量
e通过查看e表中的列中
的数据来确认t1,其中有两个不同的值:(100)和(200)。计数的列(e)显示在stat_description结果集的
列中。
其中
index_name= i2uniq
和
stat_name= n_diff_pfx02,stat_valueis 5表示索引(e,f)的两列中有五个不同的值。的不同值的列数e
和f通过查看在列中的数据证实e和f
在表t1,其中有五个不同的值:( ),(100,101),(200,102 100,103),(200,104和)( 100,105)。计数的列(e,f)显示在
stat_description 结果集的列。
可以使用innodb_index_stats表格检索表格,分区或子分区的索引大小
。在以下示例中,将为表检索索引大小
t1。有关表t1和相应索引统计信息的定义
,请参见
第14.6.12.1.6节“InnoDB持久统计信息表示例”。
MySQL的>SELECT SUM(stat_value) pages, index_name,SUM(stat_value)*@@innodb_page_size sizeFROM mysql.innodb_index_stats WHERE table_name='t1'AND stat_name = 'size' GROUP BY index_name;+ ------- + ------------ + ------- + | 页面| index_name | 大小| + ------- + ------------ + ------- + | 1 | PRIMARY | 16384 | | 1 | i1 | 16384 | | 1 | i2uniq | 16384 | + ------- + ------------ + ------- +
对于分区或子分区,WHERE可以使用具有修改子句的相同查询来检索索引大小。例如,以下查询检索表的分区的索引大小
t1:
MySQL的>SELECT SUM(stat_value) pages, index_name,SUM(stat_value)*@@innodb_page_size sizeFROM mysql.innodb_index_stats WHERE table_name like 't1#P%'AND stat_name = 'size' GROUP BY index_name;
本节介绍如何配置非持久性优化器统计信息。innodb_stats_persistent=OFF当创建或更改单个表
时,优化程序统计信息不会保存到磁盘
STATS_PERSISTENT=0。相反,统计信息存储在内存中,并在服务器关闭时丢失。统计数据也会通过某些操作和特定条件定期更新。
从MySQL 5.6.6开始,默认情况下,优化器统计信息将永久保存到磁盘,并由innodb_stats_persistent
配置选项启用
。有关持久化优化器统计信息的信息,请参见第14.6.12.1节“配置持久性优化器统计信息参数”。
非持久优化器统计信息在以下情况下更新:
在
启用该选项的情况下
运行SHOW TABLE STATUS,
SHOW INDEX或查询
INFORMATION_SCHEMA.TABLES或
INFORMATION_SCHEMA.STATISTICS表
innodb_stats_on_metadata。
在MySQL 5.6.6中默认启用持久优化器统计信息时
,默认设置
innodb_stats_on_metadata
已更改为OFF。启用
innodb_stats_on_metadata
可能会降低具有大量表或索引的模式的访问速度,并降低涉及InnoDB
表的查询的执行计划的稳定性。
innodb_stats_on_metadata全局使用SET语句进行配置
。
SET GLOBAL innodb_stats_on_metadata = ON
innodb_stats_on_metadata
仅当优化器统计信息配置为非持久性时
innodb_stats_persistent
(禁用时)才适用
。
启用启用了选项
的MySQL客户端
--auto-rehash,这是默认选项。该
auto-rehash选项会导致所有
InnoDB表被打开,并且打开的表操作会导致统计信息被重新计算。
为了改善mysql
客户端的启动时间和更新统计信息,可以auto-rehash使用该
--disable-auto-rehash
选项关闭
。该auto-rehash
功能可为交互式用户自动完成数据库,表名和列名的名称完成。
表格首先打开。
InnoDB 检测到自上次更新统计信息以来表的1/16已被修改。
MySQL查询优化器根据索引的相对选择性,使用关于密钥分发的估计
统计信息来为执行计划
选择索引。当InnoDB更新优化器统计信息时,它会对来自表上每个索引的随机页面进行采样以估计索引的
基数。(这种技术被称为
随机潜水。)
为了让您能够控制统计估计的质量(从而为查询优化器提供更好的信息),可以使用参数更改采样页面的数量
innodb_stats_transient_sample_pages。采样页面的缺省数量是8,这可能不足以产生准确的估计,导致查询优化器选择较差的索引。这种技术对于连接中使用的大型表格和表格尤为重要
。对这样的表进行不必要的
全表扫描可能是一个重大的性能问题。有关调整此类查询的提示,请参见
第8.2.1.19节“避免全表扫描”。
innodb_stats_transient_sample_pages
是可以在运行时设置的全局参数。
的值
innodb_stats_transient_sample_pages
会影响所有的指数抽样InnoDB
表和索引的时候
innodb_stats_persistent=0。当您更改索引样本大小时,请注意以下潜在的重大影响:
像1或2这样的小值可能会导致不准确的基数估计值。
增加该
innodb_stats_transient_sample_pages
值可能需要更多的磁盘读取。大于8(比如100)的值可能会导致打开表格或执行所需时间的显着减速SHOW
TABLE STATUS。
优化器可能会根据索引选择性的不同估计选择截然不同的查询计划。
无论什么样的价值
innodb_stats_transient_sample_pages
对于一个系统来说都是最好的,设置选项并将其保留在该值。选择一个值,可以对数据库中的所有表格进行合理准确的估计,而无需过多的I / O。因为统计信息会在执行时以外的其他时间自动重新计算
ANALYZE TABLE,所以增加索引样本大小,运行ANALYZE TABLE,然后再次减小样本大小没有任何意义
。
较小的表格通常比较大的表格需要较少的索引样本。如果你的数据库有很多大表,考虑使用更高的值,
innodb_stats_transient_sample_pages
如果你有大多数小表。
ANALYZE TABLEInnoDB表的复杂性
取决于:
按照定义的采样页数
innodb_stats_persistent_sample_pages。
表格中索引列的数量
分区的数量。如果一个表没有分区,则分区的数量被认为是1。
使用这些参数,估算ANALYZE TABLE复杂性的近似公式为
:
值
innodb_stats_persistent_sample_pages
索引列的*号表中的*分区数
通常,结果值越大,执行时间就越长ANALYZE TABLE。
innodb_stats_persistent_sample_pages
定义在全局级别采样的页面数量。要设置单个表格的采样页数,请使用或
的
STATS_SAMPLE_PAGES选项
。有关更多信息,请参见第14.6.12.1节“配置持久优化器统计参数”。
CREATE TABLEALTER TABLE
如果
innodb_stats_persistent=OFF,采样的页数由其定义
innodb_stats_transient_sample_pages。有关更多信息,请参见第14.6.12.2节“配置非持久性优化器统计参数”。
有关估计ANALYZE
TABLE复杂性的更深入的方法,请考虑以下示例。
在大O符号中,ANALYZE TABLE
复杂度被描述为:
O(n样本
*(n_cols_in_uniq_i
+ n_cols_in_non_uniq_i
+ n_cols_in_pk *(1 + n_non_uniq_i))
* n_part)
哪里:
n_sample是采样的页数(由其定义
innodb_stats_persistent_sample_pages)
n_cols_in_uniq_i 是所有唯一索引中所有列的总数(不包括主键列)
n_cols_in_non_uniq_i 是所有非唯一索引中所有列的总数
n_cols_in_pk是主键中的列数(如果未定义主键,
InnoDB则会在内部创建单列主键)
n_non_uniq_i 是表中非唯一索引的数量
n_part是分区的数量。如果没有定义分区,则该表被认为是单个分区。
现在,请考虑下表(表t),它具有主键(2列),唯一索引(2列)和两个非唯一索引(每个索引各有2列):
CREATE TABLE t( INT, b INT, c INT, d INT, e INT, f INT, g INT, h INT, 主键(a,b), UNIQUE KEY i1uniq(c,d), KEY i2nonuniq(e,f), KEY i3nonuniq(g,h) );
对于上述算法所需的列和索引数据,查询mysql.innodb_index_stats表的
持久索引统计表t。该
n_diff_pfx%统计显示,计数每个索引的列。例如,列
a和b主键索引计数。对于非唯一索引,除了用户定义的列以外,还会计算主键列(a,b)。
有关InnoDB
持久统计信息表的更多信息,请参见
第14.6.12.1节“配置持久性优化器统计参数”
MySQL的>SELECT index_name, stat_name, stat_descriptionFROM mysql.innodb_index_stats WHEREdatabase_name='test' ANDtable_name='t' ANDstat_name like 'n_diff_pfx%';+ ------------ + -------------- + ------------------ + | index_name | stat_name | stat_description | + ------------ + -------------- + ------------------ + | PRIMARY | n_diff_pfx01 | a | | PRIMARY | n_diff_pfx02 | a,b | | i1uniq | n_diff_pfx01 | c | | i1uniq | n_diff_pfx02 | c,d | | i2nonuniq | n_diff_pfx01 | e | | i2nonuniq | n_diff_pfx02 | e,f | | i2nonuniq | n_diff_pfx03 | e,f,a | | i2nonuniq | n_diff_pfx04 | e,f,a,b | | i3nonuniq | n_diff_pfx01 | g | | i3nonuniq | n_diff_pfx02 | g,h | | i3nonuniq | n_diff_pfx03 | g,h,a | | i3nonuniq | n_diff_pfx04 | g,h,a,b | + ------------ + -------------- + ------------------ +
根据上面显示的索引统计数据和表格定义,可以确定以下值:
n_cols_in_uniq_i,所有唯一索引中不包括主键列的所有列的总数为2(c和
d)
n_cols_in_non_uniq_i,总数在所有非唯一的索引的所有列的,为4( ,,
e 和)
fgh
n_cols_in_pk,主键中的列数是2(a和
b)
n_non_uniq_i,表中非唯一索引的数量是2(i2nonuniq和
i3nonuniq))
n_part,分区的数量是1。
您现在可以计算
innodb_stats_persistent_sample_pages*(2 + 4 + 2 *(1 + 2))* 1以确定扫描的叶页数。用
innodb_stats_persistent_sample_pages设置为默认值20,和与16的缺省页大小KiB
(innodb_page_size= 16384),则可以预计,20 * 12 * 16384 bytes
被读取为表t,或约4
MiB。
所有4个MiB不能从磁盘读取,因为一些叶页可能已经缓存在缓冲池中。
您可以配置MERGE_THRESHOLD索引页的值。如果索引页的“ 页满 ”百分比低于MERGE_THRESHOLD
删除行时的值或行缩短
UPDATE操作时的值,则
InnoDB尝试将索引页与相邻索引页合并。默认
MERGE_THRESHOLD值是50,这是以前的硬编码值。最小值
MERGE_THRESHOLD是1,最大值是50。
当索引页面的“ 页面已满 ”百分比低于50%(默认
MERGE_THRESHOLD设置)时,会
InnoDB尝试合并索引页面和相邻页面。如果两页都接近50%已满,则在页面合并后不久可能会发生页面拆分。如果这种合并分割行为频繁发生,它可能会对性能产生不利影响。为了避免频繁的合并拆分,您可以降低该MERGE_THRESHOLD值,使
InnoDB尝试页面以较低的“ 页面满 ”百分比进行合并
。以较低页面百分比合并页面会在索引页面留出更多空间,并有助于减少合并拆分行为。
该MERGE_THRESHOLD索引页面可以为表或个别指标进行定义。阿
MERGE_THRESHOLD为单个索引定义的值在一个优先MERGE_THRESHOLD
的表中定义的值。如果未定义,则该
MERGE_THRESHOLD值默认为50。
您可以MERGE_THRESHOLD使用语句的子句
来设置表的值。例如:
table_option
COMMENTCREATE TABLE
CREATE TABLE t1( id INT, KEY id_index(id) )COMMENT ='MERGE_THRESHOLD = 45';
您还可以MERGE_THRESHOLD使用以下
条款为现有表设置值
:
table_option COMMENTALTER TABLE
CREATE TABLE t1( id INT, KEY id_index(id) ); ALTER TABLE t1 COMMENT ='MERGE_THRESHOLD = 40';
要设置MERGE_THRESHOLD为单个索引值,则可以使用
与子句,
或
,如图所示在以下实施例:
index_option COMMENTCREATE TABLEALTER TABLECREATE INDEX
MERGE_THRESHOLD使用CREATE TABLE以下命令
设置单个索引:
CREATE TABLE t1( id INT, KEY id_index(id)COMMENT'MERGE_THRESHOLD = 40' );
MERGE_THRESHOLD使用ALTER TABLE以下命令
设置单个索引:
CREATE TABLE t1( id INT, KEY id_index(id) ); ALTER TABLE t1 DROP KEY id_index; ALTER TABLE t1 ADD KEY id_index(id)COMMENT'MERGE_THRESHOLD = 40';
MERGE_THRESHOLD使用CREATE INDEX以下命令
设置单个索引:
CREATE TABLE t1(id INT); CREATE INDEX id_index ON t1(id)COMMENT'MERGE_THRESHOLD = 40';
您无法修改MERGE_THRESHOLD索引级别的值GEN_CLUST_INDEX,这是在创建没有主键或唯一键索引InnoDB的InnoDB表时创建的聚簇索引。您只能通过设置
表格来修改该
MERGE_THRESHOLD值
。
GEN_CLUST_INDEXMERGE_THRESHOLD
MERGE_THRESHOLD索引
的当前值可以通过查询INNODB_SYS_INDEXES表获得
。例如:
MySQL的> SELECT * FROM INFORMATION_SCHEMA.INNODB_SYS_INDEXES WHERE NAME='id_index' \G
*************************** 1. row ******************** *******
INDEX_ID:91
名称:id_index
TABLE_ID:68
类型:0
N_FIELDS:1
PAGE_NO:4
空间:57
MERGE_THRESHOLD:40
如果使用
子句显式定义,则
可以使用它SHOW CREATE TABLE来查看MERGE_THRESHOLD表的值
:
table_option COMMENT
MySQL的> SHOW CREATE TABLE t2 \G
*************************** 1. row ******************** *******
表:t2
创建表:CREATE TABLE`t2`(
`id` int(11)DEFAULT NULL,
KEY`id_index`(`id`)COMMENT'MERGE_THRESHOLD = 40'
)ENGINE = InnoDB DEFAULT CHARSET = latin1
甲MERGE_THRESHOLD在索引级别定义的值在一个优先MERGE_THRESHOLD
的表定义的值。如果未定义,则
MERGE_THRESHOLD默认为50%(MERGE_THRESHOLD=50这是以前的硬编码值。
同样,如果使用
子句明确定义,则可以使用它SHOW INDEX来查看MERGE_THRESHOLD索引的值
:
index_option COMMENT
MySQL的> SHOW INDEX FROM t2 \G
*************************** 1. row ******************** *******
表:t2
Non_unique:1
Key_name:id_index
Seq_in_index:1
Column_name:id
整理:A
基数:0
Sub_part:NULL
已包装:NULL
空:是
Index_type:BTREE
评论:
Index_comment:MERGE_THRESHOLD = 40
该INNODB_METRICS表提供了两个计数器,可用于测量
MERGE_THRESHOLD设置对索引页合并的影响。
MySQL的>SELECT NAME, COMMENT FROM INFORMATION_SCHEMA.INNODB_METRICSWHERE NAME like '%index_page_merge%';+ ----------------------------- + ------------------- --------------------- + | NAME | 评论| + ----------------------------- + ------------------- --------------------- + | index_page_merge_attempts | 索引页合并尝试次数| | index_page_merge_successful | 成功的索引页合并数| + ----------------------------- + ------------------- --------------------- +
在降低MERGE_THRESHOLD价值时,目标是:
少量的页面合并尝试和成功的页面合并
相似数量的页面合并尝试和成功的页面合并
一个MERGE_THRESHOLD设置过小可能会导致大量的数据文件由于空页空间过量。
有关使用INNODB_METRICS计数器的信息
,请参见
第14.15.6节“InnoDB INFORMATION_SCHEMA度量标准表”。
本节涵盖与InnoDB
表空间相关的主题。
本节介绍如何增加或减少InnoDB系统表空间的大小
。
增加InnoDB系统表空间大小的最简单方法
是从头开始自动扩展。指定autoextend表空间定义中最后一个数据文件的
属性。然后InnoDB
在空间不足时以64MB为增量自动增加该文件的大小。增量大小可以通过设置innodb_autoextend_increment
以兆字节度量的系统变量的值来更改
。
您可以通过添加另一个数据文件将系统表空间扩展一个定义的数量:
关闭MySQL服务器。
如果前一个数据文件是使用关键字
autoextend定义的,则根据其实际增长的大小将其定义更改为使用固定大小。检查数据文件的大小,将其舍入到1024×1024字节(= 1MB)的最接近倍数,并在中明确指定该舍入大小
innodb_data_file_path。
在结尾添加一个新的数据文件
innodb_data_file_path,可选择使该文件自动扩展。只有最后一个数据文件
innodb_data_file_path可以指定为自动扩展。
再次启动MySQL服务器。
例如,这个表空间只有一个自动扩展的数据文件
ibdata1:
innodb_data_home_dir = innodb_data_file_path = / ibdata / ibdata1:10M:autoextend
假设这个数据文件随着时间的推移已经增长到了988MB。修改原始数据文件以使用固定大小并添加新的自动扩展数据文件后,以下是配置行:
innodb_data_home_dir = innodb_data_file_path = / ibdata / ibdata1:988M; / disk2 / ibdata2:50M:autoextend
将新数据文件添加到系统表空间配置时,请确保文件名不引用现有文件。InnoDB在重新启动服务器时创建并初始化文件。
您不能从系统表空间中删除数据文件。要减小系统表空间大小,请使用以下过程:
使用mysqldump转储所有
InnoDB表,包括
InnoDB位于MySQL数据库中的表。从5.6开始,InnoDB
MySQL数据库中包含五个表格:
MySQL的> SELECT TABLE_NAME from INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA='mysql' and ENGINE='InnoDB';
+ --------------------------- +
| TABLE_NAME |
+ --------------------------- +
| engine_cost |
| gtid_executed |
| help_category |
| help_keyword |
| help_relation |
| help_topic |
| innodb_index_stats |
| innodb_table_stats |
| 插件|
| server_cost |
| 服务器|
| slave_master_info |
| slave_relay_log_info |
| slave_worker_info |
| time_zone |
| time_zone_leap_second |
| time_zone_name |
| time_zone_transition |
| time_zone_transition_type |
+ --------------------------- +
停止服务器。
删除所有现有的表空间文件(*.ibd),包括
ibdata和ib_log
文件。不要忘记删除*.ibd
位于MySQL数据库中的表的文件。
删除表格的任何.frm文件
InnoDB。
配置一个新的表空间。
重新启动服务器。
导入转储文件。
如果您的数据库仅使用InnoDB引擎,则转储所有
数据库,停止服务器,删除所有数据库和
InnoDB日志文件,重新启动服务器以及导入转储文件可能会更简单。
要更改InnoDB
重做日志文件的数量或大小,请执行以下步骤:
停止MySQL服务器并确保它关闭而没有错误。
编辑my.cnf以更改日志文件配置。要更改日志文件大小,请配置
innodb_log_file_size。要增加日志文件的数量,请配置
innodb_log_files_in_group。
再次启动MySQL服务器。
如果InnoDB检测到
innodb_log_file_size与重做日志文件大小不同,它会写入日志检查点,关闭并删除旧的日志文件,以请求的大小创建新的日志文件,并打开新的日志文件。
您可以将原始磁盘分区用作InnoDB
系统表空间中的数据文件
。这种技术可以在Windows和某些Linux和Unix系统上启用非缓冲I / O,而无需文件系统开销。使用或不使用原始分区执行测试,以验证此更改是否实际提高了系统的性能。
在使用原始磁盘分区时,请确保运行MySQL服务器的用户标识对该分区具有读写权限。例如,如果以mysql用户身份运行服务器
,则该分区必须是可读可写的mysql。如果使用该--memlock选项运行服务器,则服务器必须运行为root,因此分区必须可读且可写root。
下面介绍的过程涉及选项文件修改。有关更多信息,请参见第4.2.6节“使用选项文件”。
创建新的数据文件时,请在newraw该innodb_data_file_path
选项的数据文件大小之后立即指定关键字
。分区必须至少与您指定的大小一样大。请注意,1MB输入InnoDB
是1024×1024字节,而磁盘规格中的1MB通常表示1,000,000字节。
的[mysqld] innodb_data_home_dir = innodb_data_file_path中=的/ dev / HDD1:3Gnewraw;的/ dev / HDD2:2Gnewraw
重新启动服务器。InnoDB通知
newraw关键字并初始化新分区。但是,请不要创建或更改任何
InnoDB表格。否则,当您下次重新启动服务器时,请InnoDB重新初始化分区,并且更改将丢失。(作为安全措施,
InnoDB防止用户在newraw指定任何分区时修改数据。)
在InnoDB初始化新分区后,停止服务器,newraw
将数据文件规范更改为raw:
的[mysqld] innodb_data_home_dir = innodb_data_file_path中=的/ dev / HDD1:3Graw;的/ dev / HDD2:2Graw
重新启动服务器。InnoDB现在允许进行更改。
在Windows系统上,适用于Linux和Unix系统的相同步骤和相应指导原则适用,只是
innodb_data_file_path在Windows上设置略有不同。
创建新数据文件时,请newraw在innodb_data_file_path
选项的数据文件大小后立即指定关键字
:
的[mysqld] innodb_data_home_dir = innodb_data_file_path中= //。/ d :: 10Gnewraw
这//./对应\\.\于访问物理驱动器的Windows语法。在上面的例子中,D:是分区的驱动器号。
重新启动服务器。InnoDB通知
newraw关键字并初始化新分区。
在InnoDB初始化新分区后,停止服务器,newraw
将数据文件规范更改为raw:
的[mysqld] innodb_data_home_dir = innodb_data_file_path中= //。/ d :: 10Graw
重新启动服务器。InnoDB现在允许进行更改。
历史上,所有InnoDB表和索引都存储在系统表空间中。这种单一的方法针对的是专门用于数据库处理的机器,精心策划的数据增长,其中任何分配给MySQL的磁盘存储都不会用于其他目的。
每个表InnoDB的
文件表空间功能提供了更灵活的选择,其中每个InnoDB表及其索引都存储在单独的
.ibd数据文件中。每个这样的
.ibd数据文件代表一个单独的
表空间。这个功能由控制
innodb_file_per_table
配置选项,该选项在MySQL 5.6.6及更高版本中默认启用。
在截断或删除存储在每个文件表的表空间中的表时,可以回收磁盘空间。截断或删除存储在共享
系统表空间中的表可在系统表空间数据文件(ibdata文件)的内部创建空闲空间,这些文件只能用于新
InnoDB数据。
同样,ALTER
TABLE驻留在共享表空间中的表上的表复制操作可以增加表空间使用的空间量。这些操作可能需要与表中的数据和索引一样多的额外空间。表复制ALTER TABLE操作所需的额外空间
不会释放回操作系统,因为它是针对每个表文件表空间的。
在TRUNCATE TABLE当存储在文件的每个表tablepaces表运行操作会比较快。
您可以将特定表存储在单独的存储设备上,用于I / O优化,空间管理或备份目的。在以前的版本中,必须将整个数据库目录移动到其他驱动器,并在MySQL数据目录中创建符号链接,如第8.12.3节“使用符号链接”中所述。在MySQL 5.6.6及更高版本中,您可以使用语法指定每个表的位置,如第14.7.5节“在数据目录外创建每个文件表空间”中所述。
CREATE TABLE ... DATA
DIRECTORY =
absolute_path_to_directory
您可以运行OPTIMIZE TABLE以压缩或重新创建每个文件表的表空间。当您运行OPTIMIZE TABLE,
InnoDB创建一个新的
.ibd具有临时名称的文件,只使用存储的实际数据所需的空间。优化完成后,InnoDB删除旧.ibd文件并将其替换为新文件。如果以前的.ibd文件显着增长,但实际数据仅占其大小的一部分,则运行OPTIMIZE
TABLE可以回收未使用的空间。
您可以移动单个InnoDB表格而不是整个数据库。
您可以将单个InnoDB表从一个MySQL实例复制到另一个(称为可
移动表空间功能)。
您可以使用动态行格式为大表BLOB或大表启用更高效的存储
。
TEXT
文件每表的表空间可能会提高成功恢复的几率,并在发生损坏时,服务器无法重新启动或备份和二进制日志不可用时节省时间。
在复制或备份表格时,每个表格文件的表空间便于每个表格的状态报告。
您可以在文件系统级别监视表大小,而无需访问MySQL。
通用Linux文件系统innodb_flush_method设置为
不允许并发写入单个文件
O_DIRECT。因此,在使用每个表的文件表空间时,可能会提高性能
innodb_flush_method。
系统表空间存储数据字典和撤消日志,并且其大小受InnoDB
表空间大小限制的限制。请参见
第14.8.1.7节“InnoDB表限制”。通过每个表文件的表空间,每个表都有其自己的表空间,这为增长空间提供了空间。
对于每个表文件的表空间,每个表可能有未使用的空间,这些空间只能被同一个表的行使用。如果管理不当,这可能会导致浪费空间。
fsync操作必须在每个打开的表上运行,而不是在单个文件上运行。由于fsync每个文件都有单独的操作,因此多个表上的写操作不能合并为单个I / O操作。这可能需要
InnoDB执行更高的fsync操作总数
。
mysqld必须为每个表保留一个打开的文件句柄,如果在每个表的文件表空间中有大量表,则这可能会影响性能。
使用更多的文件描述符。
innodb_file_per_table在MySQL 5.6.6及更高版本中默认启用。如果向后兼容MySQL 5.5或5.1,你可以考虑禁用它。在
重新创建table()的情况下,禁止
innodb_file_per_table
阻止ALTER TABLE将InnoDB表从系统表空间移动到单个.ibd文件。
ALTER TABLEALGORITHM=COPY
例如,重构InnoDB表格的聚集索引时
,将使用当前设置重新创建表格
innodb_file_per_table。添加或删除InnoDB辅助索引时,此行为不适用
。如果在不重建表格的情况下创建辅助索引,则索引与表格数据存储在同一个文件中,而不管当前innodb_file_per_table
设置如何。此行为也不适用于使用CREATE TABLE ...
TABLESPACE或
ALTER TABLE ...
TABLESPACE语法添加到系统表空间的表
。这些表格不受innodb_file_per_table
设置的影响。
如果许多表正在增长,则可能会出现更多碎片,从而妨碍DROP
TABLE性能和表扫描性能。但是,当管理碎片时,将文件放在其自己的表空间中可以提高性能。
删除每个文件表的表空间时会扫描缓冲池,对于数十GB的缓冲池,这可能需要几秒钟的时间。扫描采用广泛的内部锁执行,这可能会延迟其他操作。系统表空间中的表不受影响。
该innodb_autoextend_increment
变量定义了用于在自动扩展共享表空间文件变满时扩展其大小的增量大小(以MB为单位)的
变量不适用于无论innodb_autoextend_increment
设置如何都自动扩展的文件每表表空间文件
。最初的扩展是少量的,之后扩展以4MB为增量进行。
该innodb_file_per_table
选项默认启用。
要innodb_file_per_table在启动时设置该
选项,请使用--innodb_file_per_table
命令行选项启动服务器
,或将此行添加到以下
[mysqld]部分
my.cnf:
的[mysqld] innodb_file_per_table = 1
您也可以innodb_file_per_table
在服务器运行时动态设置
:
MySQL的> SET GLOBAL innodb_file_per_table=1;
与innodb_file_per_table
启用,可以存储InnoDB在一个表
文件。不同于tbl_name.ibdMyISAM存储引擎,与它的独立
和
tbl_name.MYD
文件进行索引和数据,tbl_name.MYIInnoDB在一个单一的数据和索引存储在一起
.ibd的文件。该
文件仍照常创建。
tbl_name.frm
如果innodb_file_per_table在启动选项中禁用
并重新启动服务器,或者使用该SET GLOBAL命令将其禁用
,则InnoDB
可以在系统表空间内创建新表,除非您已使用该CREATE TABLE ...
TABLESPACE选项将表显式地放入每个表的文件表空间或一般表空间中
。
InnoDB
无论每个文件表的设置如何,
您都可以读写任何表。
要将表从系统表空间移动到其自己的表空间,请更改
innodb_file_per_table设置并重建表:
mysql>SET GLOBAL innodb_file_per_table=1;mysql>ALTER TABLEtable_nameENGINE=InnoDB;
使用CREATE TABLE ...
TABLESPACE或
ALTER TABLE ...
TABLESPACE语法添加到系统表空间的表
不受innodb_file_per_table设置的影响
。要将这些表从系统表空间移动到每个文件表的表空间,必须使用ALTER TABLE ...
TABLESPACE语法显式移动它们
。
InnoDB总是需要系统表空间,因为它将内部数据字典
和撤消日志放在
那里。这些
.ibd文件不足以进行
InnoDB操作。
当一个表从系统表空间移出到它自己的.ibd文件中时,组成系统表空间的数据文件保持相同的大小。表格以前占用的空间可以重新用于新
InnoDB数据,但不能回收供操作系统使用。将大型
InnoDB表移出系统表空间时,如果磁盘空间有限,则可能希望innodb_file_per_table使用mysqldump命令启用
并重新创建整个实例
。如上所述,使用CREATE TABLE ...
TABLESPACE或
ALTER TABLE ...
TABLESPACE语法添加到系统表空间的表
不受影响
innodb_file_per_table
设置。这些表格必须单独移动。
要
在MySQL数据目录之外的位置创建一个按
文件表的表空间,请使用
该
语句的
子句。
DATA DIRECTORY =
absolute_path_to_directoryCREATE TABLE
提前计划位置,因为您不能DATA DIRECTORY在ALTER TABLE声明中使用
子句
以后更改位置。您指定的目录可能位于具有特定性能或容量特性的其他存储设备上,如快速
SSD或高容量
HDD。
在目标目录中,MySQL创建一个与数据库名相对应的子目录,并在其中创建新表的
.ibd文件。在MySQL目录下的数据库
DATADIR目录中,MySQL创建一个
包含表的路径名的文件。该
.isl文件是由MySQL就像一个符号链接处理。(使用实际的符号链接从未支持
table_name.islInnoDB表格。)
以下示例演示了在MySQL数据目录之外创建一个每个文件表的表空间。它显示
.ibd在指定目录中.isl创建的文件以及在MySQL数据目录下的数据库目录中创建的文件。
MySQL的>USE test;数据库改变 MySQL的>SHOW VARIABLES LIKE 'innodb_file_per_table';+ ----------------------- + ------- + | 变量名| 值| + ----------------------- + ------- + | innodb_file_per_table | ON | + ----------------------- + ------- + MySQL的>CREATE TABLE t1 (c1 INT PRIMARY KEY) DATA DIRECTORY = '#MySQL在相应的子目录中为新表创建一个.ibd文件 #到数据库名称 DB_USER @ Ubuntu的:〜/替代/目录/测试$/alternative/directory';lst1.ibd #MySQL创建一个.isl文件,其中包含目录中表的路径名 #在MySQL数据目录下 DB_USER @ Ubuntu的:〜/ MySQL的/数据/测试$lsdb.opt t1.frm t1.isl
您还可以CREATE TABLE ...
TABLESPACE与该DATA
DIRECTORY子句结合使用
,在MySQL数据目录之外创建一个每个表的文件表空间。为此,您必须指定
innodb_file_per_table为表空间名称。
MySQL的>CREATE TABLE t2 (c1 INT PRIMARY KEY) TABLESPACE = innodb_file_per_tableDATA DIRECTORY = '/alternative/directory';
innodb_file_per_table使用此方法时
不必启用
。
MySQL最初将.ibd文件保持为打开状态,从而阻止您卸载设备,但如果服务器繁忙,最终可能会关闭表。小心不要在MySQL运行时意外卸载外部设备,或者在设备断开连接时启动MySQL。尝试在关联.ibd文件丢失时访问表
会导致严重错误,需要重新启动服务器。
如果.ibd
文件仍不在预期路径中,服务器重新启动可能会失败。在这种情况下,请手动删除
数据库目录中的
文件,并在重新启动后执行
table_name.islDROP TABLE删除
.frm文件并从数据字典中删除有关表的
信息。
在将表放置在安装了NFS的卷上之前,请查看使用NFS与MySQL中概述的潜在问题 。
如果使用LVM快照,文件副本或其他基于文件的机制来备份.ibd文件,请始终FLUSH
TABLES ... FOR EXPORT首先使用该
语句,以确保在备份发生之前将缓冲在内存中的所有更改
刷新到磁盘。
本节介绍如何将每个表文件的表 空间从一个MySQL实例复制 到另一个MySQL实例,也称为可传输表空间功能。
有关其他InnoDB表复制方法的信息,请参见第14.8.1.3节“移动或复制InnoDB表”。
有很多原因可以将每个InnoDB
文件表
空间复制
到不同的实例:
只有在innodb_file_per_table设置为ON默认设置时才可以执行表空间复制过程
。驻留在共享系统表空间中的表不能停顿。
当表停顿时,受影响的表上只允许只读事务。
导入表空间时,页面大小必须与导入实例的页面大小相匹配。
DISCARD TABLESPACE不支持与父子时(主键-外键)关系表空间
foreign_key_checks设置为
1。在放弃父子表的表空间之前,设置
foreign_key_checks=0。分区
InnoDB表不支持外键。
ALTER TABLE ...
IMPORT TABLESPACE不会对导入的数据实施外键约束。如果表之间存在外键约束,则应该在相同(逻辑)时间点导出所有表。分区
InnoDB表不支持外键。
ALTER TABLE ...
IMPORT TABLESPACE并且
ALTER TABLE ...
IMPORT PARTITION ... TABLESPACE不需要
.cfg元数据文件来导入表空间。但是,导入时没有.cfg文件时不执行元数据检查,并发出类似于以下内容的警告:
消息:InnoDB:IO读取错误:(2,没有这样的文件或目录)打开'。\ test \ t.cfg',将尝试导入而没有模式验证 一排(0.00秒)
.cfg当没有预期的模式不匹配时,无需文件
导入的功能可能会更方便。另外,.cfg无法从.ibd文件中收集元数据的崩溃恢复方案中,无需文件导入的功能
可能很有用。
由于.cfg元数据文件的限制,导入分区表的表空间文件时,不会为分区类型或分区定义差异报告模式不匹配。报告列差异。
当运行
ALTER TABLE ...
DISCARD PARTITION ... TABLESPACE和
ALTER TABLE ...
IMPORT PARTITION ... TABLESPACE在subpartitioned表,无论是分区和子分区表名是允许的。当指定分区名称时,该分区的子分区将包含在该操作中。
如果两个实例都具有GA(通用可用性)状态并且它们的版本在同一个系列中,则从另一个MySQL服务器实例导入表空间文件将起作用。否则,该文件必须已在与其导入的服务器实例相同的服务器实例上创建。
在复制场景中,
innodb_file_per_table必须将其设置为ON在主设备和从设备上。
在Windows上,InnoDB以小写形式存储数据库,表空间和表名。为避免在区分大小写的操作系统(如Linux和UNIX)上导入问题,请使用小写名称创建所有数据库,表空间和表。完成此操作的一种便捷方法是在创建数据库,表空间或表之前,将以下行添加到[mysqld]
您的my.cnf或
my.ini文件的部分:
的[mysqld] 的lower_case_table_names = 1
ALTER TABLE ...
DISCARD TABLESPACE并且
ALTER TABLE
...IMPORT TABLESPACE不支持属于InnoDB常规表空间的表。有关更多信息,请参阅
CREATE TABLESPACE。
InnoDB表格
的默认行格式可以使用innodb_default_row_format
配置选项进行
配置。尝试导入未明确定义行格式(ROW_FORMAT或使用
的行)格式的表时,ROW_FORMAT=DEFAULT如果innodb_default_row_format
源实例上的设置与目标实例上的设置不同,则可能会导致模式不匹配错误
。有关相关信息,请参见
第14.11.2节“指定表格的行格式”。
导出使用InnoDB表空间加密功能加密的
表空间时
,除了元数据文件外,还会
InnoDB生成一个
文件。在对目标实例执行操作之前,必须将该
文件与文件和表空间文件
一起复制到
目标实例。该文件包含一个传输密钥和一个加密的表空间密钥。在导入时,
使用传输密钥来解密表空间密钥。有关相关信息,请参见
第14.7.10节“InnoDB表空间加密”。
.cfp.cfg.cfp.cfgALTER TABLE ...
IMPORT TABLESPACE.cfpInnoDB
如果要传输使用InnoDB表空间加密进行加密的
表,请参阅
限制和使用说明,
然后再开始获取其他过程信息。
此过程演示了如何将常规InnoDB表从正在运行的MySQL服务器实例复制
到另一个正在运行的实例。通过较小的调整,可以使用相同的过程在同一个实例上执行全表恢复。
在源实例上,创建一个不存在的表:
mysql>USE test;mysql>CREATE TABLE t(c1 INT) ENGINE=InnoDB;
在目标实例上,创建一个不存在的表:
mysql>USE test;mysql>CREATE TABLE t(c1 INT) ENGINE=InnoDB;
在目标实例上,放弃现有的表空间。(在导入表空间之前,
InnoDB必须放弃附加到接收表的表空间。)
MySQL的> ALTER TABLE t DISCARD TABLESPACE;
在源实例上,运行
FLUSH
TABLES ... FOR EXPORT以静默表并创建.cfg元数据文件:
mysql>USE test;mysql>FLUSH TABLES t FOR EXPORT;
元数据(.cfg)是在InnoDB数据目录中创建的
。
FLUSH
TABLES ... FOR EXPORT从MySQL 5.6.6开始可用。该语句确保对指定表的更改已刷新到磁盘,以便可以在实例运行时创建二进制表副本。当
FLUSH
TABLES ... FOR EXPORT运行时,
InnoDB产生了
.cfg在同一个数据库的目录表文件。该.cfg文件包含导入表空间文件时用于模式验证的元数据。
将.ibd文件和
.cfg元数据文件从源实例复制到目标实例。例如:
外壳> scp /path/to/datadir/test/t.{ibd,cfg} destination-server:/path/to/datadir/test
如下一步所述,必须在释放共享锁之前复制.ibd文件和
.cfg文件。
在源实例上,使用
UNLOCK
TABLES释放由FLUSH
TABLES ... FOR EXPORT以下项获取的锁
:
mysql>USE test;mysql>UNLOCK TABLES;
在目标实例上,导入表空间:
mysql>USE test;mysql>ALTER TABLE t IMPORT TABLESPACE;
该ALTER
TABLE ... IMPORT TABLESPACE功能不会强制导入数据的外键约束。如果表之间存在外键约束,则应该在相同(逻辑)时间点导出所有表。在这种情况下,您将停止更新表,提交所有事务,获取表上的共享锁,然后执行导出操作。
此过程演示如何将InnoDB正在运行的MySQL服务器实例的分区表复制
到另一个正在运行的实例。通过较小的调整,可以使用相同的过程InnoDB在同一实例上执行分区表的完整恢复。
在源实例上,创建一个分区表(如果不存在)。在以下示例中,将创建一个包含三个分区(p0,p1,p2)的表格:
mysql>USE test;mysql>CREATE TABLE t1 (i int) ENGINE = InnoDB PARTITION BY KEY (i) PARTITIONS 3;
在
目录中,这三个分区中的每一个都有一个单独的tablespace()文件。
/datadir/test.ibd
MySQL的> \! ls /path/to/datadir/test/
db.opt t1.frm t1#P#p0.ibd t1#P#p1.ibd t1#P#p2.ibd
在目标实例上,创建相同的分区表:
mysql>USE test;mysql>CREATE TABLE t1 (i int) ENGINE = InnoDB PARTITION BY KEY (i) PARTITIONS 3;
在
目录中,这三个分区中的每一个都有一个单独的tablespace()文件。
/datadir/test.ibd
MySQL的> \! ls /path/to/datadir/test/
db.opt t1.frm t1#P#p0.ibd t1#P#p1.ibd t1#P#p2.ibd
在目标实例上,放弃分区表的表空间。(在可以在目标实例上导入表空间之前,必须丢弃附加到接收表的表空间。)
MySQL的> ALTER TABLE t1 DISCARD TABLESPACE;
.ibd构成分区表的表空间
的三个文件从
目录中被丢弃
,留下以下文件:
/datadir/test
MySQL的> \! ls /path/to/datadir/test/
db.opt t1.frm
在源实例上,运行
FLUSH
TABLES ... FOR EXPORT静默分区表并创建.cfg元数据文件:
mysql>USE test;mysql>FLUSH TABLES t1 FOR EXPORT;
元数据(.cfg)文件(每个表空间(.ibd)文件一个)
在源实例的目录中创建
:
/datadir/test
MySQL的> \! ls /path/to/datadir/test/
db.opt t1#P#p0.ibd t1#P#p1.ibd t1#P#p2.ibd
t1.frm t1#P#p0.cfg t1#P#p1.cfg t1#P#p2.cfg
FLUSH
TABLES ... FOR EXPORT语句可确保对指定表的更改已刷新到磁盘,以便可在实例运行时进行二进制表复制。当
FLUSH
TABLES ... FOR EXPORT运行时,
InnoDB产生
.cfg在同一数据库的目录表中的表的表空间文件元数据文件。这些.cfg文件包含导入表空间文件时用于模式验证的元数据。
FLUSH
TABLES ... FOR EXPORT只能在桌面上运行,而不能在单独的桌面分区上运行。
复制.ibd和
.cfg文件从源实例数据库目录复制到目标实例数据库目录。例如:
壳> SCP /path/to/datadir/test/t1*.{ibd,cfg} destination-server:/path/to/datadir/test
如下一步所述,在释放共享锁之前.ibd,.cfg必须复制和
文件。
在源实例上,使用
UNLOCK
TABLES释放由FLUSH
TABLES ... FOR EXPORT以下项获取的锁
:
mysql>USE test;mysql>UNLOCK TABLES;
在目标实例上,导入分区表的表空间:
mysql>USE test;mysql>ALTER TABLE t1 IMPORT TABLESPACE;
此过程演示如何将InnoDB表分区从正在运行的MySQL服务器实例复制
到另一个正在运行的实例。通过较小的调整,可以使用相同的过程InnoDB在同一个实例上执行表分区恢复
。在以下示例中,将在源实例上创建一个包含四个分区(p0,p1,p2,p3)的分区表。两个分区(p2和p3)被复制到目标实例。
在源实例上,创建一个分区表(如果不存在)。在以下示例中,将创建一个包含四个分区(p0,p1,p2,p3)的表格:
mysql>USE test;mysql>CREATE TABLE t1 (i int) ENGINE = InnoDB PARTITION BY KEY (i) PARTITIONS 4;
在该
目录中,四个分区中的每一个都有一个单独的tablespace()文件。
/datadir/test.ibd
MySQL的> \! ls /path/to/datadir/test/
db.opt t1.frm t1#P#p0.ibd t1#P#p1.ibd t1#P#p2.ibd t1#P#p3.ibd
在目标实例上,创建相同的分区表:
mysql>USE test;mysql>CREATE TABLE t1 (i int) ENGINE = InnoDB PARTITION BY KEY (i) PARTITIONS 4;
在该
目录中,四个分区中的每一个都有一个单独的tablespace()文件。
/datadir/test.ibd
MySQL的> \! ls /path/to/datadir/test/
db.opt t1.frm t1#P#p0.ibd t1#P#p1.ibd t1#P#p2.ibd t1#P#p3.ibd
在目标实例上,放弃您计划从源实例导入的表空间分区。(在可以在目标实例上导入表空间分区之前,必须丢弃附加到接收表的相应分区。)
MySQL的> ALTER TABLE t1 DISCARD PARTITION p2, p3 TABLESPACE;
.ibd两个丢弃分区
的文件将从
目标实例的目录中删除
,并保留以下文件:
/datadir/test
MySQL的> \! ls /path/to/datadir/test/
db.opt t1.frm t1#P#p0.ibd t1#P#p1.ibd
当ALTER
TABLE ... DISCARD PARTITION ... TABLESPACE在子分区表上运行时,分区和子分区表名都是允许的。当指定分区名称时,该分区的子分区将包含在该操作中。
在源实例上运行
FLUSH
TABLES ... FOR EXPORT以暂停分区表并创建.cfg元数据文件。
mysql>USE test;mysql>FLUSH TABLES t1 FOR EXPORT;
元数据文件(.cfg文件)
在源实例的目录中创建
。有一个
为每个表空间(文件)文件。
/datadir/test.cfg.ibd
MySQL的> \! ls /path/to/datadir/test/
db.opt t1#P#p0.ibd t1#P#p1.ibd t1#P#p2.ibd t1#P#p3.ibd
t1.frm t1#P#p0.cfg t1#P#p1.cfg t1#P#p2.cfg t1#P#p3.cfg
FLUSH
TABLES ... FOR EXPORT语句可确保对指定表的更改已刷新到磁盘,以便可在实例运行时进行二进制表复制。当
FLUSH
TABLES ... FOR EXPORT运行时,
InnoDB产生
.cfg在同一数据库的目录表中的表的表空间文件元数据文件。这些.cfg文件包含导入表空间文件时用于模式验证的元数据。
FLUSH
TABLES ... FOR EXPORT只能在桌面上运行,而不能在单独的桌面分区上运行。
复制.ibd和
.cfg文件从源实例数据库目录复制到目标实例数据库目录。在此示例中,只有
分区2(p2)和分区3(p3)的文件.ibd和.cfg文件被复制到data目标实例上的目录。分区0(p0)和分区1(p1)保留在源实例上。
外壳> scp t1#P#p2.ibd t1#P#p2.cfg t1#P#p3.ibd t1#P#p3.cfg destination-server:/path/to/datadir/test
如下一步所述,必须在释放共享锁之前复制.ibd文件和
.cfg文件。
在源实例上,使用
UNLOCK
TABLES释放由FLUSH
TABLES ... FOR EXPORT以下项获取的锁
:
mysql>USE test;mysql>UNLOCK TABLES;
在目标实例上,导入表空间分区(p2和p3):
mysql>USE test;mysql>ALTER TABLE t1 IMPORT PARTITION p2, p3 TABLESPACE;
当ALTER
TABLE ... IMPORT PARTITION ... TABLESPACE在子分区表上运行时,分区和子分区表名都是允许的。当指定分区名称时,该分区的子分区将包含在该操作中。
以下信息描述了常规InnoDB表的可移植表空间复制过程的内部消息和错误日志消息。
何时ALTER TABLE
... DISCARD TABLESPACE在目标实例上运行:
该表被锁定在X模式下。
表空间与表分离。
在
FLUSH
TABLES ... FOR EXPORT源实例上运行时:
正在刷新导出的表被锁定在共享模式下。
清除协调程序线程停止。
脏页面被同步到磁盘。
表元数据被写入二进制
.cfg文件。
此操作的预期错误日志消息:
2013-09-24T13:10:19.903526Z 2 [注意] InnoDB:同步到磁盘的“test”。“t”开始。 2013-09-24T13:10:19.903586Z 2 [注] InnoDB:停止清除 2013-09-24T13:10:19.903725Z 2 [Note] InnoDB:将表格元数据写入'./test/t.cfg' [注意] InnoDB:Table'“test”。“t”'刷新到磁盘
在UNLOCK
TABLES源实例上运行时:
二进制.cfg文件被删除。
正在导入的一个或多个表上的共享锁被释放,清除协调器线程将重新启动。
此操作的预期错误日志消息:
2013-09-24T13:10:21.181104Z 2 [Note] InnoDB:删除元数据文件'./test/t.cfg' 2013-09-24T13:10:21.181180Z 2 [注] InnoDB:恢复清除
在ALTER TABLE
... IMPORT TABLESPACE目标实例上运行时,导入算法将为每个正在导入的表空间执行以下操作:
检查每个表空间页面是否存在损坏。
每个页面上的空间ID和日志序列号(LSN)都会更新
标志被验证并且LSN更新为标题页面。
Btree页面已更新。
页面状态设置为肮脏,以便将其写入磁盘。
此操作的预期错误日志消息:
2013-07-18 15:15:01 34960 [注意] InnoDB:为从主机'ubuntu'导出的'test / t'表导入表空间, 2013-07-18 15:15:01 34960 [注] InnoDB:第一阶段 - 更新所有页面 2013-07-18 15:15:01 34960 [注] InnoDB:与磁盘同步 2013-07-18 15:15:01 34960 [注意] InnoDB:与磁盘同步 - 完成! 2013-07-18 15:15:01 34960 [注意] InnoDB:第三阶段 - 刷新磁盘变化 2013-07-18 15:15:01 34960 [注] InnoDB:第四阶段 - 刷新完成
您还可能会收到警告,指出表空间被丢弃(如果您放弃了目标表的表空间)并显示一条消息,指出由于缺少.ibd文件而无法计算统计信息:
2013-07-18 15:14:38 34960 [Warning] InnoDB:表“test”。“t”表空间被设置为丢弃。 2013-07-18 15:14:38 7f34d9a37700 InnoDB:无法计算表“test”。“t”的统计信息,因为.ibd文件丢失。有关帮助,请参阅 http://dev.mysql.com/doc/refman/5.7/en/innodb-troubleshooting.html
撤消日志可能存储在一个或多个撤消表空间中,而不是 系统表空间中。此布局与撤消日志驻留在系统表空间中的默认配置不同。撤消日志的I / O模式使撤消表空间成为SSD存储的理想候选者 ,同时将系统表空间保留在硬盘存储上。撤消这些表空间内的表空间或单个分段不能被删除。但是,可以截断存储在撤消表空间中的撤消日志。有关更多信息,请参见 第14.7.8节“截断撤消表空间”。
要为MySQL实例配置单独的撤消表空间,请执行以下步骤。假定您在将配置部署到生产系统之前正在执行测试实例上的过程。
撤消表空间的数量只能在初始化新的MySQL实例时配置,因为该
innodb_undo_tablespaces选项只能在初始化时设置。指定的设置在MySQL实例的生命周期中是固定的。
innodb_undo_tablespaces 已弃用,将在未来版本中删除。
使用innodb_undo_directory
配置选项指定撤消表空间的目录位置
。如果未指定目录位置,则在MySQL数据目录中创建撤消表空间。
使用innodb_rollback_segments
配置选项定义回滚段的数量
。从相对较低的价值开始,并逐渐增加以检查对性能的影响。默认设置为
innodb_rollback_segments128,这也是最大值。
一个回滚段总是分配给系统表空间,32个回滚段为临时表空间(ibtmp1)保留。因此,要分配回滚段来撤消表空间,请将其设置
innodb_rollback_segments为大于33的值。例如,如果您有两个撤消表空间,请将其设置
innodb_rollback_segments为35,以便为两个撤消表空间中的每个分配一个回滚段。回滚段以循环方式分布在撤消表空间中。
当您配置单独的撤消表空间时,系统表空间中的回滚段将呈现为非活动状态。
使用该innodb_undo_tablespaces
选项定义撤消表空间的数量
。这个设置在MySQL实例的生命周期中是固定的,所以如果你不确定最优值,估计值偏高。
使用您选择的选项值创建一个新的MySQL测试实例。
在您的测试实例上使用与您的生产服务器相似的数据量来测试配置。
基准测试I / O密集型工作负载的性能。
定期增加innodb_rollback_segments性能测试的价值
并重新运行,直到I / O性能没有进一步改进。
要截断撤消表空间,MySQL实例必须配置至少两个撤消表空间。至少两个撤消表空间可确保一个撤消表空间保持活动状态,而另一个撤消表空间将被截断。撤消表空间的数量由innodb_undo_tablespaces选项定义
。默认值为0.使用此语句检查以下值
innodb_undo_tablespaces:
MySQL的> SELECT @@innodb_undo_tablespaces;
+ --------------------------- +
| @@ innodb_undo_tablespaces |
+ --------------------------- +
| 2 |
+ --------------------------- +
innodb_undo_tablespaces 已弃用,将在未来版本中删除。
有关配置撤消表空间的信息,请参见 第14.7.7节“配置撤消表空间”。
要截断撤消表空间,请启用
innodb_undo_log_truncate。
MySQL的> SET GLOBAL innodb_undo_log_truncate=ON;
当innodb_undo_log_truncate启用时,撤消超过规定的大小限制表空间文件innodb_max_undo_log_size被标记为截断。
innodb_max_undo_log_size是一个动态全局变量,默认值为1024 MiB(1073741824字节)。
MySQL的> SELECT @@innodb_max_undo_log_size;
+ ---------------------------- +
| @@ innodb_max_undo_log_size |
+ ---------------------------- +
| 1073741824 |
+ ---------------------------- +
您可以innodb_max_undo_log_size使用
SET GLOBAL语句进行配置
:
MySQL的> SET GLOBAL innodb_max_undo_log_size=2147483648;
撤销超过innodb_max_undo_log_size
设置的表空间
被标记为截断。选择用于截断的还原表空间是以循环方式执行的,以避免每次都截断同一个还原表空间。
驻留在所选撤销表空间中的回滚段将变为非活动状态,以便它们不会分配给新事务。目前正在使用回滚段的现有事务被允许完成。
该净化系统释放那些不再需要的回滚段。
在撤销表空间中的所有回滚段都被释放后,截断操作将运行并且撤消表空间将被截断为其初始大小。撤消表空间文件的初始大小取决于该
innodb_page_size值。对于默认的16k InnoDB页大小,初始撤消表空间文件大小为10MiB。对于4k,8k,32k和64k页大小,初始撤消表空间文件大小分别为7MiB,8MiB,20MiB和40MiB。
截断操作后撤消表空间的大小可能会大于初始大小,因为操作完成后会立即使用。
该innodb_undo_directory
选项定义了撤消表空间文件的位置。默认值“ 。“表示InnoDB默认情况下创建其他日志文件的目录。
MySQL的> SELECT @@innodb_undo_directory;
+ ------------------------- +
| @@ innodb_undo_directory |
+ ------------------------- +
| 。|
+ ------------------------- +
回滚段被重新激活,以便它们可以分配给新的事务。
撤消表空间不能被截断,直到其回退段被释放。通常情况下,清除系统每调用一次清除128次就释放一次回滚段。为了加快撤销表空间的截断,可以使用该
innodb_purge_rseg_truncate_frequency
选项临时增加清除系统释放回滚段的频率。默认
innodb_purge_rseg_truncate_frequency
设置是128,这也是最大值。
MySQL的> SELECT @@innodb_purge_rseg_truncate_frequency;
+ ---------------------------------------- +
| @@ innodb_purge_rseg_truncate_frequency |
+ ---------------------------------------- +
| 128 |
+ ---------------------------------------- +
要增加清除线程释放回滚段的频率,请减小
innodb_purge_rseg_truncate_frequency。例如:
MySQL的> SET GLOBAL innodb_purge_rseg_truncate_frequency=32;
撤销表空间被截断时,该表空间中的回滚段将暂时停用。其他撤消表空间中剩余的活动回滚段承担整个系统负载的责任,这可能会导致性能下降。性能下降的程度取决于许多因素,包括:
撤消表空间的数量
撤消日志的数量
撤消表空间大小
I / O susbsystem的速度
现有长时间运行的交易
系统负载
常规表空间是InnoDB
使用CREATE
TABLESPACE语法创建的共享表空间。本节中的以下主题介绍了常规表空间功能和功能:
常规表空间功能提供以下功能:
类似于系统表空间,通用表空间是可以存储多个表的数据的共享表空间。
一般的表空间比文件每表表空间有潜在的内存优势 。服务器在内存中保留表空间的元数据。较少的一般表空间中的多个表消耗的表空间元数据的内存少于单独的每个表中的表空间的相同数量的表。
通用表空间数据文件可以放置在相对于或独立于MySQL数据目录的目录中,该目录为您提供了文件每表表空间的许多数据文件和存储管理功能 。与文件每表表空间一样,将数据文件放置在MySQL数据目录之外的能力允许您分别管理关键表的性能,为特定表设置RAID或DRBD,或将表绑定到特定磁盘等。
一般的表空间支持Antelope和Barracuda文件格式,因此支持所有的表行格式和相关的功能。通过支持这两种文件格式,常规表空间不依赖于
innodb_file_format或
innodb_file_per_table
设置,这些变量也不会影响常规表空间。
该TABLESPACE选项可用于
CREATE TABLE在常规表空间,每表文件表空间或系统表空间中创建表。
该TABLESPACE选项可用于
ALTER TABLE在常规表空间,文件每表表空间和系统表空间之间移动表。以前,无法将表从每个文件表的表空间移动到系统表空间。通过一般的表空间功能,您现在可以做到这一点。
常规表空间使用CREATE TABLESPACE语法创建
。
CREATE TABLESPACE tablespace_name
ADD DATAFILE'file_name'
[FILE_BLOCK_SIZE =值]
[ENGINE [=] engine_name]一般的表空间可以在MySQL数据目录中或在MySQL数据目录之外的目录中创建。为避免与隐式创建的每个表文件表空间冲突,不支持在MySQL数据目录下的子目录中创建常规表空间。另外,在MySQL数据目录之外创建一个通用表空间时,目录必须在创建表空间之前存在。
一个.isl当MySQL数据目录之外创建一个一般的表空间文件在MySQL数据目录中创建。
例子:
在MySQL数据目录中创建一个通用表空间:
MySQL的> CREATE TABLESPACE `ts1` ADD DATAFILE 'ts1.ibd' Engine=InnoDB;
在MySQL数据目录之外的目录中创建一个通用表空间:
MySQL的> CREATE TABLESPACE `ts1` ADD DATAFILE '/my/tablespace/directory/ts1.ibd' Engine=InnoDB;
只要表空间目录不在MySQL数据目录下,就可以指定相对于MySQL数据目录的路径。在这个例子中,该
my_tablespace目录与MySQL数据目录处于同一级别:
MySQL的> CREATE TABLESPACE `ts1` ADD DATAFILE '../my_tablespace/ts1.ibd' Engine=InnoDB;
的ENGINE = InnoDB条款必须被定义为的一部分CREATE
TABLESPACE语句或InnoDB
必须被定义为默认的存储引擎(default_storage_engine=InnoDB)。
创建InnoDB常规表空间后,可以使用或
向表空间添加表,如以下示例所示:
CREATE
TABLE tbl_name ... TABLESPACE [=]
tablespace_nameALTER TABLE
tbl_name TABLESPACE [=]
tablespace_name
MySQL的> CREATE TABLE t1 (c1 INT PRIMARY KEY) TABLESPACE ts1 ROW_FORMAT=COMPACT;
MySQL的> ALTER TABLE t2 TABLESPACE ts1;
有关详细的语法信息,请参阅CREATE
TABLE和ALTER TABLE。
一般的表空间支持所有表行格式(REDUNDANT,COMPACT,
DYNAMIC,COMPRESSED)与压缩和非压缩表不能在同一个表空间一般共存的警告,由于不同的物理页面大小。
对于包含压缩表(ROW_FORMAT=COMPRESSED)的常规表空间,
FILE_BLOCK_SIZE必须指定FILE_BLOCK_SIZE值,并且该值必须是与该
值相关的有效压缩页面大小
innodb_page_size。另外,压缩表(KEY_BLOCK_SIZE)的物理页面大小必须等于
FILE_BLOCK_SIZE/1024。例如,如果
innodb_page_size=16K和
FILE_BLOCK_SIZE=8K,
KEY_BLOCK_SIZE表格的值必须是8。
下表显示了允许的
innodb_page_size,
FILE_BLOCK_SIZE和
KEY_BLOCK_SIZE组合。
FILE_BLOCK_SIZE值也可以用字节来指定。要确定KEY_BLOCK_SIZE
给定的有效值FILE_BLOCK_SIZE,请将该
FILE_BLOCK_SIZE值除以1024.表压缩不支持32K和64K
InnoDB页面大小。有关更多信息
KEY_BLOCK_SIZE,请参见
CREATE TABLE和
第14.9.1.2节“创建压缩表”。
表14.5压缩表的允许页面大小,FILE_BLOCK_SIZE和KEY_BLOCK_SIZE组合
| InnoDB页面大小(innodb_page_size) | 允许的FILE_BLOCK_SIZE值 | 允许的KEY_BLOCK_SIZE值 |
|---|---|---|
| 64K | 64K(65536) | 压缩不受支持 |
| 32K | 32K(32768) | 压缩不受支持 |
| 16K | 16K(16384) | 不适用:如果innodb_page_size等于
FILE_BLOCK_SIZE,表空间不能包含压缩表。 |
| 16K | 8K(8192) | 8 |
| 16K | 4K(4096) | 4 |
| 16K | 2K(2048) | 2 |
| 16K | 1K(1024) | 1 |
| 8K | 8K(8192) | 不适用:如果innodb_page_size等于
FILE_BLOCK_SIZE,表空间不能包含压缩表。 |
| 8K | 4K(4096) | 4 |
| 8K | 2K(2048) | 2 |
| 8K | 1K(1024) | 1 |
| 4K | 4K(4096) | 不适用:如果innodb_page_size等于
FILE_BLOCK_SIZE,表空间不能包含压缩表。 |
| 4K | 2K(2048) | 2 |
| 4K | 1K(1024) | 1 |
此示例演示如何创建常规表空间并添加压缩表。该示例假设默认
innodb_page_size值为16K。在
FILE_BLOCK_SIZE8192要求压缩表有KEY_BLOCK_SIZE8个。
MySQL的>CREATE TABLESPACE `ts2` ADD DATAFILE 'ts2.ibd' FILE_BLOCK_SIZE = 8192 Engine=InnoDB;MySQL的>CREATE TABLE t4 (c1 INT PRIMARY KEY) TABLESPACE ts2 ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=8;
如果您FILE_BLOCK_SIZE在创建常规表空间时未指定,则
FILE_BLOCK_SIZE默认为
innodb_page_size。当
FILE_BLOCK_SIZE等于
innodb_page_size,表空间可能只包含与未压缩的行格式(表COMPACT,
REDUNDANT和DYNAMIC行格式)。
您可以使用ALTER TABLE该
TABLESPACE选项将未分区的InnoDB表移动
到现有的常规表空间,新的每个文件表表空间或系统表空间。
要将非分区表从每个文件表空间或从系统表空间移动到常规表空间,请指定常规表空间的名称。常规表空间必须存在。查看CREATE TABLESPACE更多信息。
ALTER TABLE tbl_name TABLESPACE [=] tablespace_name
要将非分区表从普通表空间或每个表文件表空间移动到系统表空间,请指定
innodb_system为表空间名称。
ALTER TABLE tbl_name ... TABLESPACE [=] innodb_system
要将非分区表从系统表空间或常规表空间移动到每个文件表表空间,请指定
innodb_file_per_table为表空间名称。
ALTER TABLE tbl_name ... TABLESPACE [=] innodb_file_per_table
ALTER TABLE ... TABLESPACE操作始终会导致完整的表重建,即使该
TABLESPACE属性尚未从其先前的值更改。
ALTER TABLE ... TABLESPACE 语法不支持将表从临时表空间移动到持久表空间。
该DATA DIRECTORY条款是允许的,
CREATE TABLE ...
TABLESPACE=innodb_file_per_table但不支持与该TABLESPACE选项结合使用
。
该TABLESPACE选项可用于将单个表分区或子分区分配给
常规表空间,单独的每个表文件表空间或系统表空间。所有分区必须属于同一个存储引擎。以下示例演示了使用情况。
mysql>CREATE TABLESPACE `ts1` ADD DATAFILE 'ts1.ibd' Engine=InnoDB;mysql>CREATE TABLESPACE `ts2` ADD DATAFILE 'ts2.ibd' Engine=InnoDB;MySQL的>CREATE TABLE t1 (a INT, b INT) ENGINE = InnoDBPARTITION BY RANGE(a) SUBPARTITION BY KEY(b) (PARTITION p1 VALUES LESS THAN (100) TABLESPACE=`ts1`,PARTITION p2 VALUES LESS THAN (1000) TABLESPACE=`ts2`,PARTITION p3 VALUES LESS THAN (10000) TABLESPACE `innodb_file_per_table`,PARTITION p4 VALUES LESS THAN (100000) TABLESPACE `innodb_system`);MySQL的>CREATE TABLE t2 (a INT, b INT) ENGINE = InnoDBPARTITION BY RANGE(a) SUBPARTITION BY KEY(b) (PARTITION p1 VALUES LESS THAN (100) TABLESPACE=`ts1`(SUBPARTITION sp1,SUBPARTITION sp2),PARTITION p2 VALUES LESS THAN (1000)(SUBPARTITION sp3,SUBPARTITION sp4 TABLESPACE=`ts2`),PARTITION p3 VALUES LESS THAN (10000)(SUBPARTITION sp5 TABLESPACE `innodb_system`,SUBPARTITION sp6 TABLESPACE `innodb_file_per_table`));
该TABLESPACE选项也支持
ALTER TABLE。
MySQL的> ALTER TABLE t1 ADD PARTITION (PARTITION p5 VALUES LESS THAN (1000000) TABLESPACE = `ts1`);
如果该选项未定义,则该
操作会将该分区添加到表的默认表空间中,该表空间可以在
or 期间在表级指定。
TABLESPACE =
tablespace_nameALTER TABLE ...
ADD PARTITIONCREATE TABLEALTER TABLE
分区表上
的操作仅修改表的默认表空间。它不移动表分区。但是,在更改默认表空间后,如果未使用子句明确定义其他表空间,则重建表的操作(如使用的
操作)
会将分区移至默认表空间。
ALTER TABLE tbl_name
TABLESPACE [=]
tablespace_nameALTER TABLEALGORITHM=COPYTABLESPACE [=]
tablespace_name
要验证分区是否放置在指定的表空间中,可以查询
INFORMATION_SCHEMA.INNODB_SYS_TABLES:
MySQL的>SELECT NAME, SPACE, SPACE_TYPE FROM INFORMATION_SCHEMA.INNODB_SYS_TABLESWHERE NAME LIKE '%t1%';+ ----------------------- + ------- + ------------ + | NAME | SPACE | SPACE_TYPE | + ----------------------- + ------- + ------------ + | test / t1#P#p1#SP#p1sp0 | 57 | 一般| | test / t1#P#p2#SP#p2sp0 | 58 | 一般| | test / t1#P#p3#SP#p3sp0 | 59 | 单| | | test / t1#P#p4#SP#p4sp0 | 0 | 系统| | test / t1#P#p5#SP#p5sp0 | 57 | 一般| + ----------------------- + ------- + ------------ + MySQL的>SELECT NAME, SPACE, SPACE_TYPE FROM INFORMATION_SCHEMA.INNODB_SYS_TABLESWHERE NAME LIKE '%t2%';+ --------------------- + ------- + ------------ + | NAME | SPACE | SPACE_TYPE | + --------------------- + ------- + ------------ + | test / t2#P#p1#SP#sp1 | 57 | 一般| | test / t2#P#p1#SP#sp2 | 57 | 一般| | test / t2#P#p2#SP#sp3 | 60 | 单| | | test / t2#P#p2#SP#sp4 | 58 | 一般| | test / t2#P#p3#SP#sp5 | 0 | 系统| | test / t2#P#p3#SP#sp6 | 61 | 单| | + --------------------- + ------- + ------------ +
要将表分区移动到不同的表空间,必须使用语句移动每个分区。
ALTER TABLE
tbl_name REORGANIZE
PARTITION
以下示例演示如何将表分区移动到不同的表空间。
INFORMATION_SCHEMA.INNODB_SYS_TABLES
并被
INFORMATION_SCHEMA.INNODB_SYS_TABLESPACES
查询以验证分区是否放置在预期的表空间中。
如果该选项未在
语句中定义,请将分区移至表的默认表空间。在下面的示例中,在表级别定义的表空间是表的默认表空间
。分区从系统表空间移动到表空间,
因为
在分区语句中
没有指定任何选项
。
TABLESPACE =
tablespace_nameREORGANIZE PARTITIONInnoDBts1t1P3ts1TABLESPACEALTER TABLE t1
REORGANIZE PARTITIONP3
如果分区位于不使用子句显式定义的不同表空间中,则
重建表的ALTER TABLE操作(如使用的
操作)
ALGORITHM=COPY将分区移动到默认表空间
。
TABLESPACE [=]
tablespace_name
mysql>CREATE TABLESPACE ts1 ADD DATAFILE 'ts1.ibd';mysql>CREATE TABLESPACE ts2 ADD DATAFILE 'ts2.ibd';MySQL的>CREATE TABLE t1 ( a INT NOT NULL, PRIMARY KEY (a))ENGINE=InnoDB TABLESPACE ts1PARTITION BY RANGE (a) PARTITIONS 3 (PARTITION P1 VALUES LESS THAN (2),PARTITION P2 VALUES LESS THAN (4) TABLESPACE `innodb_file_per_table`,PARTITION P3 VALUES LESS THAN (6) TABLESPACE `innodb_system`);MySQL的>SELECT A.NAME as partition_name, A.SPACE_TYPE as space_type, B.NAME as space_nameFROM INFORMATION_SCHEMA.INNODB_SYS_TABLES ALEFT JOIN INFORMATION_SCHEMA.INNODB_SYS_TABLESPACES BON A.SPACE = B.SPACE WHERE A.NAME LIKE '%t1%' ORDER BY A.NAME;+ ---------------- + ------------ + -------------- + | partition_name | space_type | space_name | + ---------------- + ------------ + -------------- + | test / t1#P#P1 | 一般| ts1 | | test / t1#P#P2 | 单| | test / t1#P#P2 | | test / t1#P#P3 | 系统| NULL | + ---------------- + ------------ + -------------- + MySQL的>ALTER TABLE t1 REORGANIZE PARTITION P1INTO (PARTITION P1 VALUES LESS THAN (2) TABLESPACE = `ts2`);MySQL的>ALTER TABLE t1 REORGANIZE PARTITION P2INTO (PARTITION P2 VALUES LESS THAN (4) TABLESPACE = `ts2`);MySQL的>ALTER TABLE t1 REORGANIZE PARTITION P3INTO (PARTITION P3 VALUES LESS THAN (6));MySQL的>SELECT A.NAME AS partition_name, A.SPACE_TYPE AS space_type, B.NAME AS space_nameFROM INFORMATION_SCHEMA.INNODB_SYS_TABLES ALEFT JOIN INFORMATION_SCHEMA.INNODB_SYS_TABLESPACES BON A.SPACE = B.SPACE WHERE A.NAME LIKE '%t1%' ORDER BY A.NAME;+ ---------------- + ------------ + ------------ + | partition_name | space_type | space_name | + ---------------- + ------------ + ------------ + | test / t1#P#P1 | 一般| ts2 | | test / t1#P#P2 | 一般| ts2 | | test / t1#P#P3 | 一般| ts1 | + ---------------- + ------------ + ------------ +
该DROP TABLESPACE语句用于删除InnoDB一般表空间。
在DROP TABLESPACE操作之前,必须从表空间中删除所有表
。如果表空间不为空,则DROP
TABLESPACE返回错误。
如果空常规表空间DROP TABLESPACE上的操作返回错误,那么表空间可能包含孤立的临时表或中间表,这些表由被服务器出口中断的操作留下
。有关更多信息,请参见
第14.21.3节“InnoDB数据字典操作故障排除”。
ALTER TABLE
当InnoDB表空间中的最后一个表被删除时,通用表空间不会自动删除。表空间必须使用显式删除
。
DROP TABLESPACE
tablespace_name
一般的表空间不属于任何特定的数据库。一个DROP DATABASE操作可以丢弃属于一般的表空间的表,但它不能删除表空间,即使DROP
DATABASE操作下降属于该表空间中的所有表。一般的表空间必须使用明确的删除。
DROP
TABLESPACE tablespace_name
与系统表空间类似,截断或删除存储在通用表空间中的表可在通用表空间.ibd数据文件的内部创建空闲空间,该数据文件只能用于新
InnoDB数据。如果在DROP TABLE
操作过程中删除每个文件的表空间,那么空间不会释放回操作系统。
这个例子演示了如何删除一个
InnoDB通用的表空间。常规表空间ts1是使用单个表创建的。在删除表空间之前,必须删除该表。
MySQL的>CREATE TABLESPACE `ts1` ADD DATAFILE 'ts1.ibd' Engine=InnoDB;MySQL的>CREATE TABLE t1 (c1 INT PRIMARY KEY) TABLESPACE ts10 Engine=InnoDB;MySQL的>DROP TABLE t1;MySQL的>DROP TABLESPACE ts1;
是MySQL中区分大小写的标识符。
tablespace_name
生成的或现有的表空间不能更改为常规表空间。
不支持创建临时常规表空间。
常规表空间不支持临时表。
存储在常规表空间中的表只能在支持常规表空间的MySQL版本中打开。
与系统表空间类似,截断或删除存储在通用表空间中的表可在通用表空间.ibd数据文件的内部创建空闲空间,该
数据文件只能用于新InnoDB数据。空间不会释放回操作系统,因为它是用于
每个表文件的表
空间。
此外,ALTER
TABLE驻留在共享表空间(常规表空间或系统表空间)上的表的表复制操作可以增加表空间使用的空间量。这些操作需要与表中的数据和索引一样多的额外空间。表复制ALTER TABLE
操作所需的额外空间不会释放回操作系统,因为它是针对每个表文件表空间的。
ALTER TABLE ...
DISCARD TABLESPACE并且
ALTER TABLE
...IMPORT TABLESPACE不支持属于常规表空间的表。
有关更多信息,请参见第13.1.19节“CREATE TABLESPACE语法”。
InnoDB支持InnoDB存储在
每个表文件表
空间中的表的数据加密
。此功能为物理表空间数据文件提供静态加密。
InnoDB表空间加密使用由主加密密钥和表空间密钥组成的双层加密密钥体系结构。当InnoDB表被加密时,表空间密钥被加密并存储在表空间头部中。当应用程序或经过身份验证的用户想要访问加密的表空间数据时,请InnoDB
使用主加密密钥来解密表空间密钥。表空间密钥的解密版本不会改变,但主加密密钥可根据需要进行更改。此操作被称为主密钥旋转。
该InnoDB表空间加密功能依赖于一个钥匙圈插件主加密密钥管理。
所有MySQL版本都提供了一个keyring_file
插件,它将主加密密钥数据存储在由keyring_file_data配置选项指定的位置的文件中
。
InnoDBMySQL的非企业版中
的表空间加密功能使用该
keyring_file插件进行加密密钥管理。MySQL Enterprise Edition中提供的keyring_file插件和
keyring_encrypted_file插件不能作为法规遵从性解决方案。诸如PCI,FIPS和其他安全标准要求使用密钥管理系统来保护,管理和保护密钥库或硬件安全模块(HSM)中的加密密钥。
MySQL企业版提供了keyring_okv插件,其中包括一个KMIP客户端(KMIP 1.1),可与Oracle密钥保险库(OKV)配合使用来提供加密密钥管理。当
InnoDB表空间加密使用OKV进行加密密钥管理时,该功能被称为
“ MySQL企业透明数据加密(TDE) ”。
安全和强大的加密密钥管理解决方案(如OKV)对于安全和遵守各种安全标准至关重要。除了其他好处之外,使用密钥保管库可确保密钥安全存储,不会丢失,只有授权的密钥管理员才能知道密钥。密钥库也保持加密密钥的历史记录。
InnoDB表空间加密支持高级加密标准(AES)基于块的加密算法。它使用电子密码本(ECB)块加密模式进行表空间密钥加密和密码块链接(CBC)块加密模式进行数据加密。
有关InnoDB
表空间加密功能的常见问题,请参见
第A.16节“MySQL 5.7 FAQ:InnoDB表空间加密”。
密钥环插件(keyring_file插件或keyring_okv插件)必须安装和配置。钥匙扣插件安装在启动时使用该
--early-plugin-load选项执行。早期加载确保插件在InnoDB存储引擎初始化之前可用。有关密钥环插件安装和配置说明,请参见第6.5.4节“MySQL密钥环”。
一次只能启用一个密钥环插件。不支持启用多个密钥环插件。
一旦在MySQL实例中创建加密表格,创建加密表格时加载的密钥环插件必须--early-plugin-load在InnoDB初始化之前继续使用该选项加载
。否则会导致启动时和InnoDB恢复过程中出现错误
。
要验证密钥环插件是否处于活动状态,请使用该
SHOW PLUGINS语句或查询
INFORMATION_SCHEMA.PLUGINS
表。例如:
MySQL的>SELECT PLUGIN_NAME, PLUGIN_STATUSFROM INFORMATION_SCHEMA.PLUGINSWHERE PLUGIN_NAME LIKE 'keyring%';+ -------------- + --------------- + | PLUGIN_NAME | PLUGIN_STATUS | + -------------- + --------------- + | keyring_file | ACTIVE | + -------------- + --------------- +
该innodb_file_per_table
选项必须启用(默认)。
InnoDB表空间加密仅支持
文件每表的表
空间。或者,您可以TABLESPACE='innodb_file_per_table'在创建加密表或更改现有表以启用加密时指定该
选项。
在对InnoDB生产数据使用表空间加密功能之前,请确保已采取措施防止丢失主加密密钥。如果主加密密钥丢失,则存储在加密表空间文件中的数据将无法恢复。如果您正在使用该
keyring_file插件,建议您在创建第一个加密表后以及在主键旋转之前和之后立即创建密钥环数据文件的备份。密钥环数据文件位置由keyring_file_data
配置选项定义
。如果您使用
keyring_okv插件,请确保您已执行必要的操作keyring_okv
插件和Oracle密钥保管库(OKV)配置。对于keyring插件配置,请参见第6.5.4节“MySQL Keyring”。有关OKV配置,请参阅Oracle Key Vault站点上提供的OKV文档
。
要为新InnoDB表启用加密,请ENCRYPTION在CREATE TABLE语句中指定该选项
。
MySQL的> CREATE TABLE t1 (c1 INT) ENCRYPTION='Y';
要为现有InnoDB
表启用加密,请ENCRYPTION在ALTER TABLE语句中指定该选项
。
MySQL的> ALTER TABLE t1 ENCRYPTION='Y';
要禁用InnoDB表的加密,请ENCRYPTION='N'使用
ALTER TABLE。
MySQL的> ALTER TABLE t1 ENCRYPTION='N';
使用ENCRYPTION选项更改现有表格时适当地进行规划
。
ALTER TABLE ...
ENCRYPTION操作使用重建表
ALGORITHM=COPY。
ALGORITHM=INPLACE不受支持。
主密钥应定期轮换,并且每当您怀疑密钥可能已被泄漏时。
主键旋转是原子级的实例级操作。每次旋转主加密密钥时,MySQL实例中的所有表空间密钥都将重新加密并保存回其各自的表空间头文件。作为原子操作,一旦启动旋转操作,重新加密必须对所有表空间键成功。如果主密钥轮换因服务器故障而中断,请InnoDB在服务器重新启动时向前滚动操作。有关更多信息,请参阅InnoDB表空间加密和恢复。
旋转主加密密钥仅更改主加密密钥并重新加密表空间密钥。它不解密或重新加密关联的表空间数据。
旋转主加密密钥需要
SUPER特权。
要旋转主加密密钥,请运行:
MySQL的> ALTER INSTANCE ROTATE INNODB MASTER KEY;
ALTER INSTANCE
ROTATE INNODB MASTER KEY支持并发DML。但是,它不能同时与运行
CREATE TABLE ...
ENCRYPTED或
ALTER TABLE ...
ENCRYPTED作业,并采取锁来防止可能与这些陈述的并发执行出现的冲突。如果其中一个冲突语句正在运行,则必须先完成其他语句才能继续。
如果在主密钥轮换期间发生服务器故障,请
InnoDB在服务器重启时继续执行操作。
在表加密之前安装的密钥环插件必须在存储引擎初始化之前加载,以便在InnoDB初始化和恢复活动访问表空间数据之前,可以从表空间标头中检索解密表空间数据页所需的信息
。(请参阅
InnoDB表空间加密先决条件。)
当InnoDB初始化和恢复开始,主键旋转操作恢复。由于服务器故障,一些表空间密钥可能已经使用新的主密钥加密。InnoDB
从每个表空间标题读取加密数据,并且如果数据指示使用旧的主加密密钥加密表空间密钥,InnoDB
则从密钥环检索旧密钥并使用它来解密该表空间密钥。InnoDB然后使用新的主加密密钥重新加密表空间密钥,并将重新加密的表空间密钥保存回表空间标头。
导出加密表时,会InnoDB
生成一个用于加密表空间密钥的传输密钥。加密的表空间密钥和传输密钥存储在一个
文件中。该文件与加密的表空间文件一起执行导入操作。在导入时,
tablespace_name.cfpInnoDB使用传输密钥来解密
文件中的表空间密钥
。有关相关信息,请参见
第14.7.6节“将文件 - 表 - 表空间复制到另一个实例”。
tablespace_name.cfp
该ALTER
INSTANCE ROTATE INNODB MASTER KEY声明仅在主站和从站运行支持表空间加密功能的MySQL版本的复制环境中受支持。
成功的
ALTER
INSTANCE ROTATE INNODB MASTER KEY语句被写入到二进制日志中用于从站上的复制。
如果ALTER
INSTANCE ROTATE INNODB MASTER KEY语句失败,它不会记录到二进制日志中,也不会在从属系统上复制。
ALTER
INSTANCE ROTATE INNODB MASTER KEY如果密匙环插件安装在主站上而不是从站上,则
复制
操作失败。
如果keyring_file插件安装在主设备和从设备上,但从设备没有密钥环数据文件ALTER
INSTANCE ROTATE INNODB MASTER KEY,假设密钥环文件数据未缓存在内存中,则复制
语句会在从设备上创建密钥环数据文件。
ALTER
INSTANCE ROTATE INNODB MASTER KEY使用缓存在内存中的密钥环文件数据(如果可用)。
当ENCRYPTION在a CREATE TABLE或
ALTER TABLE语句中指定选项时
,它被记录在CREATE_OPTIONS字段中
INFORMATION_SCHEMA.TABLES。可以查询该字段以识别MySQL实例中的加密表。
MySQL的>SELECT TABLE_SCHEMA, TABLE_NAME, CREATE_OPTIONS FROM INFORMATION_SCHEMA.TABLESWHERE CREATE_OPTIONS LIKE '%ENCRYPTION="Y"%';+ -------------- + ------------ + ---------------- + | TABLE_SCHEMA | TABLE_NAME | CREATE_OPTIONS | + -------------- + ------------ + ---------------- + | 测试| t1 | ENCRYPTION =“Y”| + -------------- + ------------ + ---------------- +
如果服务器在正常操作期间退出或停止,建议使用之前配置的相同加密设置重新启动服务器。
当第一个新的或现有的表被加密时,第一个主加密密钥被生成。
主密钥轮换重新加密表空间密钥,但不会更改表空间密钥本身。要更改表空间密钥,您必须禁用并重新启用表加密
,这是重建表的操作。
ALTER TABLE
tbl_name ENCRYPTIONALGORITHM=COPY
如果使用COMPRESSION
and
ENCRYPTION
选项创建表
,则在表空间数据加密之前执行压缩。
keyring_file 插件使用说明:
如果密钥环数据文件(由keyring_file_data
系统变量命名的文件
)为空或缺失,则首次执行时
ALTER
INSTANCE ROTATE INNODB MASTER KEY会创建主加密密钥。
卸载keyring_file插件不会删除现有的密钥环数据文件。
建议您不要将密钥环数据文件放在与表空间数据文件相同的目录下。
keyring_file_data
在运行时
修改
系统变量或使用新keyring_file_data
设置重新启动服务器可能导致先前加密的表变得无法访问,从而导致数据丢失。
高级加密标准(AES)是唯一支持的加密算法。InnoDB表空间加密针对表空间密钥加密和密码块链接(CBC)块加密模式使用电子密码本(ECB)块加密模式进行数据加密。
改变ENCRYPTION一个表的属性是一个ALGORITHM=COPY操作。
ALGORITHM=INPLACE不受支持。
InnoDB表空间加密仅支持InnoDB存储在每个文件表
空间中的表。存储在其他InnoDB表空间类型(包括常规表空间,
系统表空间,撤消日志表空间和临时表空间)中的表不支持加密。
您无法将加密表从每个文件表表
空间移动或复制
到不受支持的InnoDB
表空间类型。
表空间加密仅适用于表空间中的数据。数据未在重做日志,撤消日志或二进制日志中加密。
从keyring_file
插件直接迁移到keyring_okv插件,反之亦然,目前不受支持。更改密钥环插件需要解密表,卸载当前的密钥环插件,安装和配置其他密钥环插件以及重新加密表。
本节涵盖与InnoDB
表格和索引相关的主题。
本节涵盖与InnoDB
表格相关的主题。
要创建一个InnoDB表,请使用该
CREATE TABLE语句。
CREATE TABLE t1(INT,b CHAR(20),PRIMARY KEY(a))ENGINE = InnoDB;
ENGINE=InnoDB
如果InnoDB定义为缺省存储引擎,则
不需要指定该子句。要检查默认存储引擎,请发出以下语句:
MySQL的> SELECT @@default_storage_engine;
+ -------------------------- +
| @@ default_storage_engine |
+ -------------------------- +
| InnoDB |
+ -------------------------- +
ENGINE=InnoDB如果您计划使用mysqldump或复制来重放CREATE TABLE默认存储引擎所在的服务器上的语句,
您仍然可以使用子句InnoDB。
一个InnoDB表及其索引可以在系统表空间,文件一个
表表
空间或
一般表空间中创建。何时启用
innodb_file_per_table(默认情况下),会InnoDB
在单个每个文件表的表空间中隐式创建一个表。相反,
innodb_file_per_table禁用时,会InnoDB在InnoDB系统表空间中隐式创建一个表。要在常规表空间中创建表,请使用
CREATE TABLE ...
TABLESPACE语法。有关更多信息,请参见
第14.7.9节“InnoDB常规表空间”。
在创建InnoDB表时,MySQL会在MySQL数据目录下的数据库目录中创建一个.frm文件。有关.frm文件的更多信息,请参阅
InnoDB表和.frm文件。对于在每个表文件表空间中创建的表,MySQL 默认在数据库目录中创建一个
.ibd表空间文件。在创建的表
InnoDB的系统表空间在现有的创建ibdata文件,它驻留在MySQL数据目录。在通用表空间中创建的表是在现有的通用表空间
.ibd文件中创建的。一般的表空间文件可以在MySQL数据目录内部或外部创建。有关更多信息,请参见
第14.7.9节“InnoDB常规表空间”。
在内部,InnoDB将每个表的条目添加到InnoDB数据字典中。该条目包括数据库名称。例如,如果
t1在test
数据库中创建表,则数据库名称的数据字典条目为
'test/t1'。这意味着您可以t1在不同的数据库中创建同名()的表,并且表名不会在内部发生冲突
InnoDB。
MySQL将数据字典信息存储在数据库目录中的
.frm文件中。与其他MySQL存储引擎不同,
InnoDB它还在系统表空间内的内部数据字典中编码有关该表的信息。当MySQL删除一个表或数据库时,它会删除一个或多个.frm文件以及InnoDB
数据字典中的相应条目。InnoDB
仅通过移动.frm文件就无法在数据库之间移动表格
。有关移动InnoDB表的信息
,请参见
第14.8.1.3节“移动或复制InnoDB表”。
InnoDB表格
的默认行格式由innodb_default_row_format
配置选项定义,该
选项的默认值为
DYNAMIC。
Dynamic
和
Compressed
行格式允许您利用
InnoDB表格压缩和长列值的高效离页存储等功能。要使用这些行格式,
innodb_file_per_table必须启用(默认为MySQL 5.6.6),并且
innodb_file_format必须设置为梭子鱼。
SET GLOBAL innodb_file_per_table = 1; SET GLOBAL innodb_file_format =梭子鱼; CREATE TABLE t3(INT,b CHAR(20),PRIMARY KEY(a))ROW_FORMAT = DYNAMIC; CREATE TABLE t4(INT,b CHAR(20),PRIMARY KEY(a))ROW_FORMAT = COMPRESSED;
或者,您可以使用
CREATE TABLE ...
TABLESPACE语法InnoDB在常规表空间中创建
表。常规表空间支持所有行格式。有关更多信息,请参见第14.7.9节“InnoDB常规表空间”。
CREATE TABLE t1(c1 INT PRIMARY KEY)TABLESPACE ts1 ROW_FORMAT = DYNAMIC;
CREATE TABLE ...
TABLESPACE语法也可用于在系统表空间中创建
InnoDB具有
Dynamic行格式的表格,以及具有Compact
或Redundant行格式的表格。
CREATE TABLE t1(c1 INT PRIMARY KEY)TABLESPACE = innodb_system ROW_FORMAT = DYNAMIC;
有关InnoDB行格式的更多信息,请参见第14.11节“InnoDB行存储和行格式”。有关如何确定InnoDB表格的行格式和InnoDB
行格式的物理特性,请参见第14.8.1.2节“InnoDB表的物理行结构”。
总是为表定义一个主键InnoDB,指定一列或多列:
被最重要的查询引用。
永远不要空白。
永远不要有重复的值。
很少,如果曾经插入改变价值。
例如,在包含人员信息的表格中,您不会创建主键,(firstname,
lastname)因为不止一个人可以拥有相同的姓名,有的人姓名空白,有时人们更改姓名。有了这么多的约束条件,通常没有明显的一组列用作主键,因此您可以使用数字ID创建一个新列作为主键的全部或一部分。您可以声明
自动增量
列,以便在插入行时自动填充升序值:
#ID的值可以像不同表格中相关项目之间的指针。 CREATE TABLE t5(id INT AUTO_INCREMENT,b CHAR(20),PRIMARY KEY(id)); #主键可以由多个列组成。任何autoinc列必须先到达。 CREATE TABLE t6(id INT AUTO_INCREMENT,INT,b CHAR(20),PRIMARY KEY(id,a));
虽然表格在没有定义主键的情况下工作正常,但主键涉及许多性能方面,并且是任何大型或经常使用的表格的关键设计方面。建议您始终在CREATE
TABLE语句中指定主键。如果您创建表,加载数据,然后运行ALTER TABLE以稍后添加主键,则该操作比创建表时定义主键慢得多。
要查看InnoDB表格的属性,请发表SHOW TABLE STATUS
声明:
MySQL的> SHOW TABLE STATUS FROM test LIKE 't%' \G;
*************************** 1. row ******************** *******
名称:t1
引擎:InnoDB
版本:10
Row_format:紧凑
行数:0
Avg_row_length:0
Data_length:16384
Max_data_length:0
Index_length:0
Data_free:0
Auto_increment:NULL
Create_time:2015-03-16 15:13:31
Update_time:NULL
Check_time:NULL
整理:latin1_swedish_ci
校验和:NULL
Create_options:
评论:
一排(0.00秒)
有关SHOW TABLE
STATUS输出的信息,请参见
第13.7.5.36节“SHOW TABLE STATUS语法”。
InnoDB表格属性也可以使用InnoDB信息模式系统表查询:
MySQL的> SELECT * FROM INFORMATION_SCHEMA.INNODB_SYS_TABLES WHERE NAME='test/t1' \G
*************************** 1. row ******************** *******
TABLE_ID:45
NAME:test / t1
FLAG:1
N_COLS:5
空间:35
FILE_FORMAT:羚羊
ROW_FORMAT:紧凑
ZIP_PAGE_SIZE:0
SPACE_TYPE:单一
一排(0.00秒)
有关更多信息,请参见 第14.15.3节“InnoDB INFORMATION_SCHEMA系统表”。
表的物理行结构InnoDB取决于创建表时指定的行格式。如果未指定行格式,则使用默认行格式。InnoDB
表格的默认行格式由innodb_default_row_format
配置选项定义,该
选项的默认值为
DYNAMIC。
以下各节介绍InnoDB行格式的特性
。
有关InnoDB行格式的更多信息,请参见第14.11节“InnoDB行存储和行格式”。
要确定InnoDB
表格的行格式,请使用SHOW TABLE STATUS。例如:
MySQL的> SHOW TABLE STATUS IN test1\G
*************************** 1. row ******************** *******
名称:t1
引擎:InnoDB
版本:10
Row_format:动态
行数:0
Avg_row_length:0
Data_length:16384
Max_data_length:0
Index_length:16384
Data_free:0
Auto_increment:1
Create_time:2016-09-14 16:29:38
Update_time:NULL
Check_time:NULL
整理:latin1_swedish_ci
校验和:NULL
Create_options:
评论:
您也可以InnoDB通过查询来确定表格
的行格式
INFORMATION_SCHEMA.INNODB_SYS_TABLES。
MySQL的> SELECT NAME, ROW_FORMAT FROM INFORMATION_SCHEMA.INNODB_SYS_TABLES WHERE NAME='test1/t1';
+ ---------- + ------------ +
| NAME | ROW_FORMAT |
+ ---------- + ------------ +
| test1 / t1 | 动态|
+ ---------- + ------------ +
该REDUNDANT格式可用于保持与旧版本MySQL的兼容性。
行中InnoDB使用的表
REDUNDANT行格式具有以下特点:
每个索引记录包含一个6字节的标题。标题用于链接连续的记录,也用于行级锁定。
聚集索引中的记录包含所有用户定义列的字段。另外,还有一个6字节的事务ID字段和一个7字节的滚动指针字段。
如果没有为表定义主键,则每个聚簇索引记录还包含一个6字节的行ID字段。
每个二级索引记录还包含为聚簇索引键定义的所有不在二级索引中的主键字段。
记录包含指向记录每个字段的指针。如果记录中字段的总长度小于128字节,则指针是一个字节; 否则,两个字节。这些指针的数组称为记录目录。这些指针指向的区域称为记录的数据部分。
内部InnoDB存储固定长度字符列,如
CHAR(10)固定长度格式。InnoDB不会从VARCHAR列中截断尾随空格
。
InnoDB将长度大于或等于768字节的固定长度字段编码为可变长度字段,可将其存储在页外。例如,CHAR(255)如果字符集的最大字节长度大于3,则列可能会超过768个字节
utf8mb4。
SQL NULL值在记录目录中保留一个或两个字节。除此之外,NULL如果存储在可变长度列中,则SQL
值在记录的数据部分中保留零字节。在固定长度的列中,它在记录的数据部分中保留列的固定长度。为NULL
值保留固定空间使得可以将列更新
NULL为非NULL
值,而不会造成索引页的碎片化。
与COMPACT格式相比,行格式将行存储空间减少了大约20%,但这会
REDUNDANT增加某些操作的CPU使用量。如果您的工作负载是受缓存命中率和磁盘速度限制的典型负载,则
COMPACT格式可能会更快。如果工作负载是一个受CPU速度限制的罕见情况,则紧凑格式可能会变慢。
行中InnoDB使用的表
COMPACT行格式具有以下特点:
每个索引记录都包含一个5字节的标题,其前面可以有一个可变长度的标题。标题用于链接连续的记录,也用于行级锁定。
记录标题的可变长度部分包含一个用于指示NULL列的位向量。如果索引中的列数可以
NULL是N,则位向量占用
字节。(例如,如果有9到16列的任何位置,则位矢量使用两个字节。)列
CEILING(N/8)NULLNULL不要占用这个向量中的位以外的空间。标题的可变长度部分也包含可变长度列的长度。每个长度需要一个或两个字节,具体取决于列的最大长度。如果索引中的所有列都
NOT NULL具有固定长度,则记录标题不包含可变长度部分。
对于每个非NULL可变长度字段,记录标题以一个或两个字节包含列的长度。只有部分列存储在溢出页面的外部或最大长度超过255个字节且实际长度超过127个字节时才需要两个字节。对于外部存储的列,2字节长度表示内部存储部分的长度加上指向外部存储部分的20字节指针。内部部分是768字节,所以长度是768 + 20。20字节的指针存储列的真实长度。
记录头后面是非NULL列的数据内容。
聚集索引中的记录包含所有用户定义列的字段。另外,还有一个6字节的事务ID字段和一个7字节的滚动指针字段。
如果没有为表定义主键,则每个聚簇索引记录还包含一个6字节的行ID字段。
每个二级索引记录还包含为聚簇索引键定义的所有不在二级索引中的主键字段。如果这些主键字段中的任何一个是可变长度,则每个二级索引的记录标题都有一个可变长度部分来记录它们的长度,即使二级索引是在固定长度列上定义的。
在内部,对于不可变长度字符集,
InnoDB存储固定长度字符列(如CHAR(10)固定长度格式)。
InnoDB不会从VARCHAR
列中截断尾随空格。
在内部,对于可变长度字符集(例如
utf8mb3和)utf8mb4,
InnoDB尝试通过修剪尾部空格来
以字节为单位进行存储
。如果
列值的字节长度
超过字节,
则将尾随空格修剪为列值字节长度的最小值。
列的最大长度
是最大字符字节长度×
。
CHAR(N)NCHAR(N)NInnoDBCHAR(N)N
InnoDB保留最少的
N字节
。
在很多情况下保留最小空间可以在不造成索引页碎片的情况下就地完成列更新。通过比较,对于,
列占据的最大字符字节长度×
。
CHAR(N)NROW_FORMAT=REDUNDANTCHAR(N)N
InnoDB将长度大于或等于768字节的固定长度字段编码为可变长度字段,可将其存储在页外。例如,CHAR(255)如果字符集的最大字节长度大于3,则列可能会超过768个字节
utf8mb4。
ROW_FORMAT=DYNAMIC并像
ROW_FORMAT=COMPRESSED处理CHAR存储一样处理
存储ROW_FORMAT=COMPACT。
本节介绍将某些或所有InnoDB表移动或复制
到其他服务器或实例的技术。例如,您可能将整个MySQL实例移动到更大,更快的服务器; 您可能会将整个MySQL实例克隆到新的复制从服务器; 您可以将单个表复制到另一个实例以开发和测试应用程序,或者复制到数据仓库服务器以生成报告。
在Windows上,InnoDB始终以小写形式存储数据库和表名。要将数据库以二进制格式从Unix移动到Windows或从Windows移动到Unix,请使用小写名称创建所有数据库和表。完成此操作的一种便捷方法是在创建任何数据库或表之前,将以下行添加到[mysqld]您的my.cnf或my.ini文件的
部分
:
的[mysqld] 的lower_case_table_names = 1
移动或复制InnoDB表格的技巧包括:
可移动表空间功能用于
FLUSH
TABLES ... FOR EXPORT准备InnoDB
表以便从一个服务器实例复制到另一个服务器实例。要使用此功能,InnoDB必须创建表并
innodb_file_per_table设置为
ON使每个InnoDB表都有其自己的表空间。有关使用信息,请参见
第14.7.6节“将每个文件表空间复制到另一个实例”。
MySQL企业备份产品可让您备份正在运行的MySQL数据库,同时最大限度地减少操作中断,同时生成数据库的一致快照。当MySQL Enterprise Backup正在复制表时,读取和写入操作可以继续。另外,MySQL Enterprise Backup可以创建压缩备份文件,并备份表的子集。结合MySQL二进制日志,您可以执行时间点恢复。MySQL企业备份包含在MySQL企业订阅中。
有关MySQL企业备份的更多详细信息,请参见 第29.2节“MySQL企业备份概述”。
InnoDB只需复制第14.18.1节“InnoDB备份”中 “冷备份”下列出的所有相关文件
即可移动数据库
。
InnoDB数据和日志文件在具有相同浮点数格式的所有平台上都是二进制兼容的。如果浮点格式不同,但您没有使用
表FLOAT或
DOUBLE数据类型,则过程相同:只需复制相关文件即可。
在移动或复制每个.ibd
文件的文件时,源系统和目标系统上的数据库目录名称必须相同。存储在InnoDB共享表空间中的表定义
包括数据库名称。存储在表空间文件中的事务ID和日志序列号在数据库之间也不同。
要将.ibd文件和关联的表从一个数据库移动到另一个数据库,请使用以下RENAME
TABLE语句:
RENAME TABLEdb1.tbl_nameTOdb2.tbl_name;
如果你有一个“ 干净 ”的.ibd文件备份
,你可以将它恢复到源自它的MySQL安装,如下所示:
自从您复制.ibd文件以来,该表格一定不能被删除或截断,因为这样做会更改存储在表空间内的表格ID。
发出此ALTER TABLE声明以删除当前.ibd文件:
ALTER TABLE tbl_nameDISCARD TABLESPACE;
将备份.ibd文件复制到适当的数据库目录。
发出此ALTER TABLE声明以告诉InnoDB使用.ibd该表的新
文件:
ALTER TABLE tbl_nameIMPORT TABLESPACE;
该ALTER TABLE
... IMPORT TABLESPACE功能不会强制导入数据的外键约束。
在这种情况下,“ 干净 ” .ibd
文件备份是满足以下要求的文件备份:
.ibd文件中
的交易没有未提交的修改
。
.ibd文件
中没有未合并的插入缓冲区条目
。
清除已从.ibd文件中删除所有删除标记的索引记录
。
mysqld已经将.ibd文件的所有修改过的页面从缓冲池刷新
到文件中。
您可以.ibd使用以下方法创建一个干净的备份文件:
停止来自mysqld服务器的所有活动并提交所有事务。
等待,直到SHOW
ENGINE INNODB STATUS显示数据库中没有活动事务,并且InnoDBis 的主线程状态
Waiting for server
activity。然后你可以制作一个.ibd文件的副本
。
另一种制作.ibd文件干净副本的方法
是使用MySQL企业备份产品:
使用MySQL企业备份来备份
InnoDB安装。
在备份上
启动第二个mysqld服务器,并让它清理备份中的.ibd文件。
您可以使用mysqldump在一台机器上转储您的表,然后在另一台机器上导入转储文件。使用这种方法,格式是否不同或表中是否包含浮点数据无关紧要。
提高此方法性能的一种方法是在导入数据时关闭 自动提交模式,假定表空间具有足够的空间用于导入事务生成的大回滚段。仅在导入整个表格或表格的一部分后执行提交。
如果您MyISAM想要将表格转换InnoDB为更好的可靠性和可扩展性,请在转换之前查看以下指南和技巧。
在转换离开MyISAM表格时,降低key_buffer_size配置选项的值
以释放缓存结果不再需要的内存。增加innodb_buffer_pool_size
配置选项的值,该
选项执行类似于为InnoDB表分配缓存内存的角色。该
InnoDB 缓冲池可以缓存表数据和索引数据,加快了查询,查找并保持查询结果在内存中进行再利用。有关缓冲池大小配置的指导,请参见
第8.12.4.1节“MySQL如何使用内存”。
在繁忙的服务器上,运行关闭查询缓存的基准测试。该InnoDB缓冲池提供类似的好处,所以查询缓存可能会不必要地占用内存。有关查询缓存的信息,请参见
第8.10.3节“MySQL查询缓存”。
因为MyISAM表不支持
事务处理,所以您可能没有太注意
autocommit配置选项和COMMIT和
ROLLBACK
语句。这些关键字对于允许多个会话同时读取和写入InnoDB表很重要,可在写入繁重的工作负载中提供可观的可伸缩性优势。
在事务处于打开状态时,系统将在事务开始时保留数据快照,如果系统在杂散事务继续运行时插入,更新和删除数百万行,则会导致大量开销。因此,请注意避免长时间运行的交易:
如果您正在使用mysql会话进行交互式实验,请务必
COMMIT(完成更改)或
ROLLBACK(撤消更改)完成。关闭交互式会话,而不是让它们长时间保持打开状态,以避免意外长时间保持交易的开放。
ROLLBACK是一个相对昂贵的操作,因为
INSERT,
UPDATE和之前的
DELETE操作都写入InnoDB表中
COMMIT,期望大多数更改都成功提交,并且回滚很少。在试验大量数据时,避免对大量行进行更改,然后回滚这些更改。
当使用一系列INSERT语句加载大量数据时
,请定期
COMMIT检查结果以避免持续几个小时的事务。在数据仓库的典型加载操作中,如果出现问题,则截断表(使用TRUNCATE
TABLE)并从头开始,而不是执行
ROLLBACK。
上述技巧可以节省在过长的事务中浪费的内存和磁盘空间。当事务比他们应该更短时,问题是过多的I / O。每个
COMMITMySQL都确保每个更改都安全地记录到磁盘上,这涉及到一些I / O。
对于InnoDB桌子上的大多数操作,您应该使用该设置
autocommit=0。从效率的角度看,这样就避免了在发出大量连续的不必要的I / O
INSERT,
UPDATE或
DELETE语句。从安全角度来看,ROLLBACK
如果您在mysql命令行或应用程序中的异常处理程序中犯了错误,则可以发出
语句来恢复丢失或乱码的数据。
autocommit=1适用于InnoDB表格
的时间是运行一系列查询以生成报告或分析统计数据的时间。在这种情况下,不存在与COMMIT或
相关的I / O损失ROLLBACK,并且InnoDB可以
自动优化只读工作负载。
如果您进行了一系列相关更改,请在最后单独完成所有更改
COMMIT。例如,如果您将相关信息插入到多个表中,请COMMIT
在完成所有更改后执行一次。或者,如果您运行了许多连续的
INSERT语句,请COMMIT在加载完所有数据后执行一个语句
; 如果你在做数百万条
INSERT语句,可能会通过发行COMMIT每一万条或者十万条记录来分割巨大的交易
,所以交易不会变得太大。
请记住,即使是SELECT
语句也会打开一个事务,因此在交互式mysql
会话中运行一些报告或调试查询之后,请发出COMMIT
或关闭mysql会话。
您可能会在MySQL错误日志中看到引用“ 死锁 ”的警告消息
,或者输出
SHOW ENGINE INNODB
STATUS。尽管名字可怕,但
死锁对于InnoDB表格来说并不是一个严重的问题,并且通常不需要采取任何纠正措施。当两个事务开始修改多个表时,以不同顺序访问表时,它们可以达到每个事务正在等待另一个事务并且两者都不能继续的状态。当
启用死锁检测时(默认),MySQL立即检测到这种情况并取消(回滚)
“ 较小 ”交易,让对方继续。如果使用innodb_deadlock_detect
配置选项禁用死锁检测
,则InnoDB依赖该
innodb_lock_wait_timeout设置来回滚死锁情况下的事务。
无论哪种方式,您的应用程序都需要错误处理逻辑来重新启动由于死锁而被强制取消的事务。当您重新发布与之前相同的SQL语句时,原始计时问题不再适用。另一个交易已经完成并且您可以继续,或者其他交易仍在进行中,并且您的交易等待完成。
如果经常发生死锁警告,您可以查看应用程序代码以一致的方式对SQL操作进行重新排序,或者缩短事务处理时间。您可以使用innodb_print_all_deadlocks启用的选项进行测试,
以查看MySQL错误日志中的所有死锁警告,而不仅仅是SHOW ENGINE INNODB
STATUS输出中的最后警告
。
有关更多信息,请参见第14.5.5节“InnoDB中的死锁”。
为了从InnoDB表中获得最佳性能,您可以调整与存储布局相关的多个参数。
当您将MyISAM是大的,经常访问的,并保持至关重要的数据表,调查和考虑innodb_file_per_table,
innodb_file_format以及
innodb_page_size配置选项,以及
ROW_FORMAT
和KEY_BLOCK_SIZE条款中的
CREATE TABLE说法。
在最初的实验中,最重要的设置是
innodb_file_per_table。当启用这个设置时,这是MySQL 5.6.6的默认设置,新的
InnoDB表格将隐式创建在
每个文件表的表
空间中。与InnoDB系统表空间相比,每个表文件表空间允许操作系统在截断或删除表时回收磁盘空间。File-per-table表空间还支持
Barracuda文件格式和相关功能,例如表压缩,针对长可变长度列的高效页外存储以及大型索引前缀。有关更多信息,请参见
第14.7.4节“InnoDB文件 - 每个表空间”。
您还可以将InnoDB表存储在共享的常规表空间中。常规表空间支持梭子鱼文件格式,可以包含多个表。有关更多信息,请参见
第14.7.9节“InnoDB常规表空间”。
转换非InnoDB表使用
InnoDB用途ALTER
TABLE:
ALTER TABLE table_nameENGINE = InnoDB;
不要转换在MySQL系统表
mysql从数据库MyISAM
的InnoDB类型。这是一个不受支持的操作。类型。
您可以创建一个InnoDB表,它是MyISAM表的一个副本,而不是ALTER
TABLE用于执行转换,以便在切换之前并行测试旧表和新表。
创建一个InnoDB具有相同列和索引定义的空表。使用看到完整的
语句中使用。将该子句更改为
。
SHOW CREATE TABLE
table_name\GCREATE TABLEENGINEENGINE=INNODB
要将大量数据传输到InnoDB如前一节所示创建的空
表中,请插入行。
INSERT INTO
innodb_table SELECT * FROM
myisam_table ORDER BY
primary_key_columns
InnoDB
插入数据后,
您还可以为表格创建索引。历史上,创建新的二级索引对于InnoDB来说是一个缓慢的操作,但是现在,您可以在索引创建步骤中以相对较少的开销加载数据之后创建索引。
如果您UNIQUE对辅助键有限制,则可以通过在导入操作过程中暂时关闭唯一性检查来加速表导入:
SET unique_checks = 0;
... import operation ...
SET unique_checks = 1;
对于大型表,这可以节省磁盘I / O,因为
InnoDB可以使用其
更改缓冲区将二级索引记录作为批次写入。确保数据不包含重复的密钥。
unique_checks允许但不要求存储引擎忽略重复密钥。
为了更好地控制插入过程,您可以分片插入大表:
INSERT INTO新建表SELECT * FROM oldtable WHERE yourkey>somethingAND yourkey <=somethingelse;
插入所有记录后,您可以重命名表格。
在大表转换期间,增加InnoDB缓冲池的大小
以减少磁盘I / O,最大为物理内存的80%。您还可以增加InnoDB日志文件的大小。
如果您打算InnoDB在转换过程中在表中创建数据的临时数据副本,
建议您以file-per-table表空间创建表,以便在删除表时可以回收磁盘空间。当
innodb_file_per_table
启用配置选项时(默认),新创建的
InnoDB表格将隐式创建在file-per-table表空间中。
无论您是MyISAM直接转换表还是创建克隆InnoDB表,请确保在此过程中有足够的磁盘空间来保存旧表和新表。
InnoDB表需要比MyISAM表更多的磁盘空间。
如果ALTER TABLE操作空间不足,则会启动回滚,如果磁盘受限,则可能需要几个小时。对于插入,InnoDB使用插入缓冲区将二级索引记录合并到索引中。这节省了大量的磁盘I / O。对于回滚,不使用这种机制,并且回滚可能比插入长30倍。
在失控回滚的情况下,如果数据库中没有有价值的数据,建议终止数据库进程而不是等待数百万个磁盘I / O操作完成。有关完整的过程,请参见 第14.21.2节“强制InnoDB恢复”。
该PRIMARY KEY子句是影响MySQL查询性能和表和索引空间使用情况的关键因素。主键唯一标识表中的一行。表中的每一行都必须具有主键值,并且没有两行可以具有相同的主键值。
这些是主键的准则,其次是更详细的解释。
PRIMARY KEY为每个表
声明一个。通常,WHERE查找单个行时,它是您在子句中引用的最重要的列。
PRIMARY KEY在原始CREATE TABLE
声明中
声明该子句,而不是稍后通过ALTER TABLE声明添加它
。
仔细选择列及其数据类型。喜欢字符或字符串的数字列。
如果没有使用另一个稳定的,唯一的,非空的数字列,请考虑使用自动增量列。
如果怀疑主键列的值是否可以更改,那么自动增加列也是一个不错的选择。更改主键列的值是一项昂贵的操作,可能涉及重新排列表内和每个二级索引内的数据。
考虑将主键添加到任何尚未拥有主键的表中。根据表格的最大投影尺寸使用最小的实际数字类型。这可以使每行更紧凑,这可以为大型表格节省大量空间。如果表具有任何二级索引,则空间节省将成倍增加 ,因为主键值在每个二级索引条目中都会重复。除了减少磁盘上的数据大小外,小型主键还可以让更多数据适合 缓冲池,加快各种操作并提高并发性。
如果表在某些较长的列(例如a)上已经有一个主键VARCHAR,则考虑添加一个新的无符号
AUTO_INCREMENT列并将主键切换为该主键,即使该列未在查询中引用。这种设计更改可以在二级索引中节省大量空间。您可以指定以前的主键列UNIQUE NOT NULL来强制执行与该PRIMARY KEY子句相同的约束,即防止所有这些列出现重复值或空值。
如果您将相关信息分布在多个表中,则通常每个表使用相同的列作为其主键。例如,人事数据库可能有多个表,每个表都有一个员工编号的主键。销售数据库可能包含一些带有客户编号主键的表格,以及其他具有订单编号主键的表格。由于使用主键的查找速度非常快,因此可以为这些表构造高效的连接查询。
如果你PRIMARY KEY完全不用这个子句,MySQL会为你创建一个看不见的东西。这是一个6字节的值,可能比您需要的时间更长,从而浪费空间。因为它是隐藏的,所以你不能在查询中引用它。
InnoDB需要比等效MyISAM表更多的磁盘存储
的可靠性和可扩展性功能
。您可以稍微更改列和索引定义,以便更好地利用空间,减少处理结果集时的I / O和内存消耗,以及更有效地使用索引查找的查询优化计划。
如果您为主键设置了数字标识列,请使用该值与任何其他表中的相关值进行交叉引用,特别是对于连接查询。例如,不是接受国家名称作为输入并执行查询搜索相同的名称,而是执行一次查找以确定国家/地区ID,然后执行其他查询(或单个连接查询)在多个表中查找相关信息。而不是将客户或目录项目编号存储为一串数字,可能会占用多个字节,请将其转换为数字标识以存储和查询。一个4字节的无符号数
INT专栏可以索引超过40亿项目(美国的含义为10亿:10亿)。有关不同整数类型的范围,请参见
第11.2.1节“整型(精确值) - INTEGER,INT,SMALLINT,TINYINT,MEDIUMINT,BIGINT”。
InnoDB提供了一种可配置的锁定机制,可以显着提高将行添加到具有AUTO_INCREMENT列的表的SQL语句的可伸缩性和性能
。要在表中
使用该
AUTO_INCREMENT机制,
必须将列定义为索引的一部分,以便可以在表上执行等效的索引查找以获取最大列值。通常,这是通过将列设置为某个表索引的第一列来实现的。
InnoDBAUTO_INCREMENTSELECT
MAX(ai_col)
本节介绍AUTO_INCREMENT锁定模式的行为,
不同AUTO_INCREMENT锁定模式设置的使用含义以及如何InnoDB初始化
AUTO_INCREMENT计数器。
本节介绍AUTO_INCREMENT用于生成自动增量值的锁定模式的行为
以及每种锁定模式如何影响复制。自动增量锁定模式在启动时使用innodb_autoinc_lock_mode
配置参数进行
配置。
以下术语用于描述
innodb_autoinc_lock_mode
设置:
“ INSERT类似 ”的
陈述
在表中生成新的行中的所有语句,包括INSERT,
INSERT ...
SELECT,REPLACE,
REPLACE ...
SELECT,和LOAD
DATA。包括“ 简单插入 ”,
“ 批量插入 ”和“ 混合模式 ”
插入。
“ 简单插入 ”
可以预先确定要插入的行数的语句(最初处理语句时)。这包括单行和多行
INSERT以及
REPLACE没有嵌套子查询但没有的语句
INSERT
... ON DUPLICATE KEY UPDATE。
“ 批量插入 ”
预先不知道要插入的行数(以及所需自动增量值的数量)的语句。这包括
INSERT ...
SELECT,
REPLACE ...
SELECT和LOAD
DATA声明,但不是简单的
INSERT。在处理每一行时,一次为列InnoDB
分配新的值
AUTO_INCREMENT。
“ 混合模式插入 ”
这些是“ 简单插入 ”语句,用于为新行的某些(但不是全部)行指定自动递增值。下面c1是一个例子,其中
是一
AUTO_INCREMENT列表格
t1:
INSERT INTO t1(c1,c2)VALUES(1,'a'),(NULL,'b'),(5,'c'),(NULL,'d');
另一种类型的“ 混合模式插入 ”是
INSERT
... ON DUPLICATE KEY UPDATE,在最坏的情况下,INSERT
其后是a UPDATE,其中AUTO_INCREMENT在更新阶段期间可能或不可能使用列的分配值
。
innodb_autoinc_lock_mode
配置参数
有三种可能的设置
。对于“ 传统 ”,“ 连续 ”或
“ 交错 ”锁定模式,设置分别为0,1或2
。
innodb_autoinc_lock_mode = 0
(“ 传统 ”锁定模式)
传统的锁定模式提供了与innodb_autoinc_lock_mode
在MySQL 5.1中引入配置参数之前相同的行为
。传统的锁定模式选项提供了向后兼容性,性能测试和解决“混合模式插入”的问题,这是由于可能的语义差异。
在这种锁定模式下,所有“ INSERT-like ”
语句都会获得一个特殊的表级
AUTO-INC锁,用于插入带有AUTO_INCREMENT列的表中。通常将该锁保持在语句的末尾(而不是结束事务),以确保自动递增值以给定INSERT语句序列的可预测和可重复的顺序进行分配
,并确保自动递增值由任何给定的语句分配都是连续的。
在基于语句的复制的情况下,这意味着在从属服务器上复制SQL语句时,自动增量列将使用与主服务器上相同的值。执行多条INSERT语句的结果是确定性的,并且从设备复制与主设备上相同的数据。如果由多个INSERT语句生成的自动递增值被交错,那么两个并发INSERT语句的结果
将是不确定的,并且不能可靠地使用基于语句的复制传播到从属服务器。
为了清楚说明,请考虑使用此表的示例:
CREATE TABLE t1( c1 INT(11)NOT NULL AUTO_INCREMENT, c2 VARCHAR(10)DEFAULT NULL, 主键(c1) )ENGINE = InnoDB;
假设有两个事务正在运行,每个事务都将行插入带有AUTO_INCREMENT列的表中
。一个事务使用INSERT ...
SELECT插入1000行的语句,另一个事务使用
插入一行的简单
INSERT语句:
Tx1:INSERT INTO t1(c2)从另一个表中选择1000行... Tx2:INSERT INTO t1(c2)VALUES('xxx');
InnoDB无法预先知道从Tx1 SELECT中的
INSERT语句中检索了多少行
,并且随着语句的进行一次一个地分配自动递增值。通过在表达式末尾保存一个表级锁,每次只能执行一个
INSERT引用表的语句t1,并且不会交错由不同语句产生的自增号。由Tx1 INSERT ...
SELECT语句生成的自动递增值
是连续的,并且由()使用的(单个)自动递增值
INSERT在Tx2中的语句要么小于要么大于用于Tx1的所有语句,这取决于哪个语句首先执行。
只要从二进制日志(使用基于语句的复制或恢复场景中)重播时SQL语句以相同顺序执行,结果与第一次运行Tx1和Tx2时的结果相同。因此,表级锁一直持续到语句结束时INSERT
使用自动增量安全来使用基于语句的复制。但是,当多个事务同时执行插入语句时,这些表级锁会限制并发性和可伸缩性。
在前面的示例中,如果没有表级锁定,则INSERTTx2中使用的自动增量列的值
取决于执行语句的时间。如果
INSERTTx2在INSERTTx1运行时(而不是在它开始之前或完成之后)执行,则由两个INSERT语句分配的特定自动递增值是非确定性的,并且可能因运行而异。
在
连续
锁定模式下,InnoDB可以避免对预先知道行数的“ 简单插入 ”语句使用表级AUTO-INC锁
,并且仍然保留基于语句的复制的确定性执行和安全性。
如果您没有使用二进制日志重播SQL语句作为恢复或复制的一部分,
则可以使用交叉锁定模式来消除对表级AUTO-INC锁定的所有使用,
以实现更高的并发性和性能,代价是允许自动分离 - 由语句分配的增量编号,并且可能通过并行执行语句交错分配编号。
innodb_autoinc_lock_mode = 1
(“ 连续 ”锁定模式)
这是默认的锁定模式。在这种模式下,“ 批量插入 ”使用特殊的
AUTO-INC表级锁,并保持它直到语句结束。这适用于所有
INSERT ...
SELECT,
REPLACE ...
SELECT和LOAD
DATA语句。一次AUTO-INC只能执行一个持有该锁的语句
。如果大容量插入操作的源表与目标表不同,则AUTO-INC
在从源表中选择的第一行执行共享锁后,将对目标表执行锁定。如果批量插入操作的源和目标是同一个表,AUTO-INC在对所有选定行进行共享锁定之后进行锁定。
“ 简单插入 ”(预先知道要插入的行数)AUTO-INC通过在互斥体(轻量级锁)的控制下获得所需数量的自动增量值来避免表级
锁定在分配过程的持续时间内保持,
不直到语句完成。AUTO-INC除非AUTO-INC另一个事务持有锁,否则不使用表级锁。如果另一个事务持有一个
AUTO-INC锁,一个“ 简单插入 ”等待AUTO-INC
锁,就好像它是一个“ 批量插入 ”。
这种锁定模式可以确保在出现INSERT预先未知行数的语句的情况下
(以及在语句进行时自动递增数字的位置),所有由“ INSERT类似 ”
语句指定的自动递增值
都是连续的,操作对于基于语句的复制是安全的。
简而言之,这种锁定模式显着提高了可扩展性,同时可以安全地使用基于语句的复制。此外,与“ 传统 ” 锁定模式一样,任何给定语句分配的自动递增数字都是连续的。有 没有变化在语义比较 “ 传统 ”对于使用自动递增,有一个重要的例外,任何声明模式。
“ 混合模式插入 ”
例外,其中用户为AUTO_INCREMENT多行“ 简单插入 ”中的某些行(但不是全部)的行提供显式值
。对于这样的插入,InnoDB分配比要插入的行数更多的自动增量值。但是,自动分配的所有值都会连续生成(并因此高于)最近执行的前一个语句生成的自动递增值。“ 超额 ”号码丢失。
innodb_autoinc_lock_mode = 2
(“ 交错 ”锁定模式)
在这种锁定模式下,没有
“ INSERT-like ”
语句使用表级AUTO-INC
锁定,并且可以同时执行多个语句。这是最快和最可伸缩的锁定模式,但当从二进制日志中重播SQL语句时,使用基于语句的复制或恢复方案时,这种方式并不安全。
在此锁定模式下,自动递增值保证在所有同时执行的“ INSERT类似 ”
语句中是唯一且单调递增的
。但是,由于多个语句可能同时生成数字(也就是说,数字的分配是跨越语句交错的),所以为任何给定语句插入的行生成的值可能不连续。
如果执行的唯一语句是提前知道要插入的行数的“ 简单插入 ”,则除了“ 混合模式插入 ”外,对于单个语句生成的数字没有间隔 。但是,执行 “ 批量插入 ”时,可能会有由任何给定语句分配的自动递增值中的空白。
在复制时使用自动增量
如果您正在使用基于语句的复制,请将其设置
innodb_autoinc_lock_mode
为0或1,并在主服务器及其从服务器上使用相同的值。如果您使用innodb_autoinc_lock_mode
= 2(“ interleaved ”)或者主设备和从设备不使用相同锁定模式的配置,则自动递增值不能保证在主设备上与主设备上
的相同。
如果您使用的是基于行或混合格式的复制,则所有自动增量锁定模式都是安全的,因为基于行的复制对SQL语句的执行顺序不敏感(并且混合格式使用基于行的复制任何对基于语句的复制不安全的语句)。
“ 丢失 ”自动递增值和序列差距
在所有锁定模式(0,1和2)中,如果生成自动递增值的事务回退,那些自动递增值将“ 丢失 ”。一旦为自动增量列生成值,无论是否
“ INSERT类似 ”
语句完成,以及是否回滚包含的事务,都无法回滚它。这些丢失的值不会被重复使用。因此,AUTO_INCREMENT表格的列中存储的值可能存在间隙
。
为AUTO_INCREMENT列
指定NULL或0
在所有的锁模式(0,1,2),如果用户指定NULL或0用于AUTO_INCREMENT在列INSERT,
InnoDB将行仿佛没有指定值,并且生成用于它的新值。
为AUTO_INCREMENT列
指定一个负值
在所有锁定模式(0,1和2)中,如果为AUTO_INCREMENT
列指定负值,则不会定义自动递增机制的行为。
如果该AUTO_INCREMENT值变得大于指定整数类型的最大整数
在所有锁定模式(0,1和2)中,如果值大于可以存储在指定整数类型中的最大整数,则自动递增机制的行为未定义。
“ 批量插入 ”的 自动增量值的间隔
与
innodb_autoinc_lock_mode
设定为0(“ 传统 ”)或1(“ 连续 ”),通过任何给定语句生成的自动递增的值是连续的,没有间隙,这是因为表级AUTO-INC
锁一直保持到该语句的末尾,只有一个这样的陈述可以一次执行。
与
innodb_autoinc_lock_mode
设置为2(“ 交织 ”),有可能是在所产生的自动递增值间隙“ 批量插入, ”但只有当有同时执行的
“ INSERT样 ”
的语句。
对于锁定模式1或2,连续的语句之间可能会出现间隙,因为对于批量插入,每个语句所需的自动递增值的确切数量可能不知道,并且可能会高估。
自动增加由“ 混合模式插入 ”指定的值
考虑一个“ 混合模式插入 ”,其中
“ 简单插入 ”指定一些(但不是全部)结果行的自动增量值。这种语句在锁定模式0,1和2中表现不同。例如,假设c1是AUTO_INCREMENT表格的一
列
t1,并且最近自动生成的序列号是100。
mysql>CREATE TABLE t1 (- >c1 INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,- >c2 CHAR(1)- >) ENGINE = INNODB;
现在,考虑下面的“ 混合模式插入 ”语句:
MySQL的> INSERT INTO t1 (c1,c2) VALUES (1,'a'), (NULL,'b'), (5,'c'), (NULL,'d');
随着
innodb_autoinc_lock_mode
设置为0(“ 传统 ”),这四个新的行是:
MySQL的> SELECT c1, c2 FROM t1 ORDER BY c2;
+ ----- + ------ +
| c1 | c2 |
+ ----- + ------ +
| 1 | a |
| 101 | b |
| 5 | c |
| 102 | d |
+ ----- + ------ +
下一个可用自动递增值为103,因为自动递增值一次分配一次,而不是在语句执行开始时一次全部分配。这个结果是真实的是否有并发执行
“ INSERT样 ”
(任何类型的)陈述。
随着
innodb_autoinc_lock_mode
设置为1(“ 连续 ”),这四个新行也:
MySQL的> SELECT c1, c2 FROM t1 ORDER BY c2;
+ ----- + ------ +
| c1 | c2 |
+ ----- + ------ +
| 1 | a |
| 101 | b |
| 5 | c |
| 102 | d |
+ ----- + ------ +
但是,在这种情况下,下一个可用自动递增值是105,而不是103,因为在处理语句时分配了四个自动递增值,但只使用了两个。这个结果是真实的是否有并发执行
“ INSERT样 ”
(任何类型的)陈述。
与
innodb_autoinc_lock_mode
设定为模式2(“ 交织 ”),四个新的行是:
MySQL的>SELECT c1, c2 FROM t1 ORDER BY c2;+ ----- + ------ + | c1 | c2 | + ----- + ------ + | 1 | a | |x| b | | 5 | c | |y| d | + ----- + ------ +
值和x和
y是唯一的,比以前生成的任何行都大。然而,具体的数值x,并
y依赖于并行执行语句生成自动递增值的数量。
最后,考虑当最近生成的序列号为100时发布的以下语句:
MySQL的> INSERT INTO t1 (c1,c2) VALUES (1,'a'), (NULL,'b'), (101,'c'), (NULL,'d');
使用任何
innodb_autoinc_lock_mode
设置,此语句会生成重复键错误23000(Can't write; duplicate key in
table),因为101分配给该行,(NULL, 'b')并且该行的
插入
(101, 'c')失败。
AUTO_INCREMENT在一系列INSERT语句
中
修改列值
在所有锁定模式(0,1和2)中,修改语句AUTO_INCREMENT序列中间的
列值
INSERT可能会导致“ 重复输入 ”错误。例如,如果执行将
列值UPDATE更改为AUTO_INCREMENT大于当前最大自动增量值的INSERT
操作,则未指定未使用的自动增量值的后续操作可能会遇到“ 重复输入 ”
错误。以下示例演示了此行为。
mysql>CREATE TABLE t1 (- >c1 INT NOT NULL AUTO_INCREMENT,- >PRIMARY KEY (c1)- >) ENGINE = InnoDB;MySQL的>INSERT INTO t1 VALUES(0), (0), (3);MySQL的>SELECT c1 FROM t1;+ ---- + | c1 | + ---- + | 1 | | 2 | | 3 | + ---- + MySQL的>UPDATE t1 SET c1 = 4 WHERE c1 = 1;MySQL的>SELECT c1 FROM t1;+ ---- + | c1 | + ---- + | 2 | | 3 | | 4 | + ---- + MySQL的>INSERT INTO t1 VALUES(0);错误1062(23000):键'PRIMARY'的重复条目'4'
本节介绍如何InnoDB
初始化AUTO_INCREMENT计数器。
如果AUTO_INCREMENT为InnoDB表指定列,则InnoDB数据字典中的表句柄
包含一个称为自动增量计数器的专用计数器,该计数器用于为该列分配新值。该计数器仅存储在主存储器中,而不是存储在磁盘上。
要在服务器重新启动后初始化自动增量计数器InnoDB,请将第一次插入时的以下语句的等效语句执行到包含AUTO_INCREMENT列的表中。
SELECT MAX(ai_col)FROM table_nameFOR UPDATE;
InnoDB递增由语句检索到的值并将其分配给表中的列和自动递增计数器。默认情况下,该值将增加1.此默认值可由auto_increment_increment
配置设置覆盖
。
如果表格为空,则InnoDB使用该值1。该默认设置可以被auto_increment_offset
配置设置覆盖。
如果SHOW TABLE STATUS
语句在自动递增计数器初始化之前检查该表,则InnoDB初始化但不增加该值。该值被存储以供稍后插入使用。此初始化在表上使用正常的独占锁定读取,并且锁持续到事务结束。InnoDB遵循相同的过程来初始化新创建的表的自动增量计数器。
在自动递增计数器初始化之后,如果您没有明确指定AUTO_INCREMENT列的值
,则
InnoDB递增计数器并将新值赋给该列。如果插入明确指定列值的行,并且该值大于当前计数器值,则将计数器设置为指定的列值。
InnoDB只要服务器运行,就会使用内存自动增量计数器。当服务器停止并重新启动时,如前所述,InnoDB重新初始化第一个表的每个表的计数器
INSERT。
服务器重新启动也会取消表和
语句中的表选项
的效果
,您可以使用它们来设置初始计数器值或更改当前计数器值。
AUTO_INCREMENT =
NCREATE TABLEALTER TABLEInnoDB
该如何InnoDB存储引擎处理下,本节中的下列主题介绍外键约束:
有关外键使用信息和示例,请参见 第13.1.18.6节“使用外键约束”。
InnoDB表的
外键定义受以下条件限制:
InnoDB允许外键引用任何索引列或一组列。但是,在被引用的表中,必须有一个索引,其中被引用的列按照相同顺序列为
第一列。
InnoDB目前不支持具有用户定义分区的表的外键。这意味着没有用户分区的
InnoDB表可能包含外键引用或外键引用的列。
InnoDB允许外键约束引用非唯一键。这是InnoDB对标准SQL 的
扩展。
InnoDB表的
外键引用操作
受以下条件限制:
虽然SET DEFAULT被MySQL服务器允许,但被拒绝为无效
InnoDB。CREATE
TABLE并ALTER
TABLE利用这一条款语句不得用于InnoDB表。
如果父表中有多个具有相同引用键值的InnoDB
行,则在外键中执行操作就好像其他具有相同键值的父行不存在一样。例如,如果您定义了一个RESTRICT类型约束,并且存在具有多个父行的子行,InnoDB则不允许删除这些父行中的任何行。
InnoDB 基于对应于外键约束的索引中的记录,通过深度优先算法执行级联操作。
如果ON UPDATE CASCADE或者ON
UPDATE SET NULL递归更新它在级联期间先前更新过的
同一个表,它的行为就像
RESTRICT。这意味着你不能使用自引用ON UPDATE CASCADE
或ON UPDATE SET NULL操作。这是为了防止级联更新导致的无限循环。自引用的ON DELETE SET
NULL,在另一方面,是可能的,因为是自引用ON DELETE CASCADE。级联操作的嵌套深度不得超过15层。
一般来说,就像MySQL一样,在一个SQL语句中,可以逐行插入,删除或更新许多行,InnoDB
检查UNIQUE和FOREIGN
KEY约束。执行外键检查时,InnoDB在必须查看的子记录或父记录上设置共享的行级锁。InnoDB立即检查外键约束; 该检查不会延迟到事务提交。根据SQL标准,默认行为应该是延迟检查。也就是说,只有在处理完整个SQL语句后才能检查约束。直到
InnoDB 实现延迟约束检查,有些事情是不可能的,比如删除一个使用外键引用自己的记录。
在一个外键约束
存储生成列无法使用ON UPDATE
CASCADE,ON DELETE SET NULL,
ON UPDATE SET NULL,ON DELETE
SET DEFAULT,或ON UPDATE SET
DEFAULT。
外键约束不能引用 虚拟生成的列。
在5.7.16之前,外键约束不能引用在虚拟生成列上定义的辅助索引。
在MySQL 5.7.13及更早版本中,InnoDB
不允许在索引虚拟生成列的基本列上使用级联参照操作定义外键约束
。MySQL 5.7.14中解除了这个限制。
在MySQL 5.7.13及更早版本中,InnoDB
不允许在显式包含在虚拟索引中的非虚拟外键列上定义级联参照操作。MySQL 5.7.14中解除了这个限制。
您可以从查询INFORMATION_SCHEMA.KEY_COLUMN_USAGE
表中获得关于外键及其用法的一般信息
,更多关于InnoDB表更具体的信息
可以在
INNODB_SYS_FOREIGN和
INNODB_SYS_FOREIGN_COLS表中,也可以在INFORMATION_SCHEMA数据库中找到。
除了SHOW ERRORS涉及InnoDB表的外键错误
(通常是MySQL服务器中的错误150),您可以InnoDB通过检查输出来获得最近一次外键错误
的详细解释SHOW ENGINE
INNODB STATUS。
InnoDB本部分的下列主题介绍
了表格限制:
不要不转换在MySQL系统表
mysql从数据库
MyISAM到InnoDB表。这是一个不受支持的操作。如果这样做,MySQL将不会重新启动,直到您从备份中还原旧系统表或通过重新初始化数据目录重新生成它们(请参见第2.10.1节“初始化数据目录”)。
在使用NFS之前InnoDB,请查看使用NFS与MySQL中概述的潜在问题
。
一个表最多可以包含1017列(在MySQL 5.6.9中从前面的限制1000提高)。虚拟生成的列包含在此限制中。
一个表最多可以包含64个 二级索引。
如果innodb_large_prefix启用(默认),则对于InnoDB使用的表格
DYNAMIC
或
COMPRESSED
行格式,索引键前缀限制为3072字节。如果
innodb_large_prefix禁用,则任何行格式的表的索引键前缀限制为767字节。
innodb_large_prefix 已弃用,将在未来版本中删除。
innodb_large_prefix在MySQL 5.5中引入,以禁用大型索引键前缀,以便与InnoDB不支持大型索引键前缀的早期版本兼容
。
对于InnoDB使用REDUNDANT
或
COMPACT
行格式的表,
索引键前缀长度限制为767字节
。例如,您可能会
在a 或
列上使用列前缀索引超过255个字符
来达到此限制
,并假设为aTEXTVARCHARutf8mb3字符集和每个字符的最大长度为3个字节。
尝试使用超过限制的索引键前缀长度将返回错误。为避免复制配置中出现此类错误,请避免启用
innodb_large_prefix在主服务器上启用它,如果它也不能在从服务器上启用。
适用于索引键前缀的限制也适用于全列索引键。
如果通过在创建MySQL实例时指定选项将InnoDB
页面大小减小到8KB或4KB
innodb_page_size,则根据16KB页面大小的3072字节的限制,索引键的最大长度将按比例降低。也就是说,当页面大小为8KB时,最大索引关键字长度为1536字节,当页面大小为4KB时,最大索引关键字长度为768字节。
多列索引最多允许16列。超出限制会返回错误。
错误1070(42000):指定的关键部件过多; 最多允许16个零件
最大行长度,除了可变长度列(VARBINARY,
VARCHAR,
BLOB和
TEXT),是比对于4KB,8KB,16KB,32KB和页大小的页的一半稍少。例如,默认innodb_page_size16KB 的最大行长度
大约为8000字节。对于InnoDB64KB 的页面大小,最大行长度大约为16000字节。
LONGBLOB并且
LONGTEXT
列的长度必须小于4GB,并且行的总长度包括BLOB和
TEXT列)必须小于4GB。
如果一行的长度小于半页,则所有行都存储在本地页面中。如果它超过半页,则可以选择可变长度的列用于外部页外存储,直到该行适合半页内为止,如第14.12.2节“文件空间管理”中所述。
虽然 InnoDB内部支持大于65,535字节的行大小,但MySQL本身对所有列的总大小施加了65,535的行大小限制:
mysql>CREATE TABLE t (a VARCHAR(8000), b VARCHAR(10000),- >c VARCHAR(10000), d VARCHAR(10000), e VARCHAR(10000),- >f VARCHAR(10000), g VARCHAR(10000)) ENGINE=InnoDB;错误1118(42000):行大小太大。最大的行大小 使用表类型,不计算BLOB,是65535.你必须改变一些 列转换为TEXT或BLOB
在一些较旧的操作系统上,文件必须小于2GB。这不是InnoDB
它本身的限制,但是如果你需要一个大的表空间,使用几个较小的数据文件而不是一个大的数据文件来配置它。
InnoDB日志文件
的组合大小可以达到512GB。
最小的表空间大小略大于10MB。最大的表空间大小取决于
InnoDB页面大小。
最大表空间大小也是表的最大大小。
默认页面大小InnoDB为16KB。您可以通过innodb_page_size在创建MySQL实例时配置选项来增加或减少页面大小
。
ROW_FORMAT=COMPRESSED在
梭子鱼的文件格式假定页面大小最多为16KB,并使用14位指针。
支持32KB和64KB的页面大小,但
ROW_FORMAT=COMPRESSED不支持大于16KB的页面大小。对于32KB和64KB页面大小,最大记录大小为16KB。因为
innodb_page_size=32k,范围的大小是2MB。因为
innodb_page_size=64k,范围大小是4MB。
使用特定InnoDB页面大小的MySQL实例
不能使用来自使用不同页面大小的实例的数据文件或日志文件。
ANALYZE TABLE通过对每个索引树执行随机潜伏并相应地更新索引基数估计来确定索引基数(如
输出Cardinality栏中所示
SHOW INDEX)。因为这些只是估计,重复运行可能会产生不同的数字。这使得快速
ANALYZE
TABLEANALYZE TABLEInnoDB表格但不是100%准确,因为它没有考虑所有行。
您可以进行
统计
的收集ANALYZE TABLE
更精确,通过打开更稳定的
innodb_stats_persistent
配置选项,在解释
第14.6.12.1“配置持续优化程序统计参数”。启用该设置后,重要的是ANALYZE TABLE在对索引列数据进行重大更改之后运行
,因为不会定期重新计算统计信息(例如重新启动服务器之后)。
如果启用持续统计设置,则可以通过修改innodb_stats_persistent_sample_pages
系统变量来更改随机潜水次数
。如果持久统计设置被禁用,请修改
innodb_stats_transient_sample_pages
系统变量。
MySQL在连接优化中使用索引基数估计。如果连接没有以正确的方式进行优化,请尝试使用ANALYZE TABLE。在少数情况下,您的查询ANALYZE
TABLE不会产生足够好的值,您可以使用FORCE
INDEX查询来强制使用特定索引,或设置
max_seeks_for_key系统变量以确保MySQL优先于表扫描查找索引。参见第B.5.5节“与优化器相关的问题”。
如果语句或事务在一个表上运行,并且ANALYZE TABLE在同一个表
上运行,然后执行第二个
ANALYZE TABLE操作,则第二个ANALYZE TABLE
操作将被阻止,直到语句或事务完成。出现此现象的原因
是ANALYZE TABLE当ANALYZE TABLE完成运行时将当前加载的表定义标记为过时
。新的陈述或交易(包括第二个ANALYZE TABLE
语句)必须将新的表定义加载到表缓存中,直到当前正在运行的语句或事务完成并清除旧的表定义时才会发生这种情况。加载多个并发表定义不受支持。
SHOW TABLE STATUSInnoDB
除了表中保留的物理尺寸以外,不提供关于表的准确统计信息。行数只是SQL优化中使用的粗略估计。
InnoDB不保留表中行的内部计数,因为并发事务可能同时
“ 看到 ”不同数量的行。因此,SELECT COUNT(*)
语句只计算当前事务可见的行。
在MySQL 5.7.18之前,通过扫描聚集索引来InnoDB处理
SELECT COUNT(*)语句。从MySQL 5.7.18开始,
通过遍历较小的二级索引(如果存在)来InnoDB处理SELECT
COUNT(*)语句。
SELECT COUNT(*)如果索引记录不完全在缓冲池中,
处理语句需要一些时间。为了加快计数,您可以创建一个计数器表并让应用程序根据插入操作对其进行更新并删除它。但是,在数千个并发事务正在启动对同一个计数器表的更新的情况下,此方法可能无法很好地扩展。如果大致的行数足够,
SHOW TABLE STATUS可以使用。
InnoDB
以相同的方式处理SELECT
COUNT(*)和SELECT COUNT(1)操作。没有性能差异。
在Windows上,InnoDB始终以小写形式存储数据库和表名。要将数据库以二进制格式从Unix移动到Windows或从Windows移动到Unix,请使用小写名称创建所有数据库和表。
一AUTO_INCREMENT列
ai_col必须被定义为一个指数,使得它能够进行一个索引的等效的部分上的表查找以获得最大列值。通常,这是通过将列设置为某个表索引的第一列来实现的。
SELECT
MAX(ai_col)
InnoDB在与AUTO_INCREMENT列相关联的索引的末尾设置排他锁,
同时初始化AUTO_INCREMENT表中先前指定的
列。
随着
innodb_autoinc_lock_mode=0,
InnoDB使用一个特殊的
AUTO-INC地方在访问自动增长计数器获得锁并保持至当前的SQL语句的结束表锁定模式。在AUTO-INC锁定表格锁定时,其他客户端无法插入表格
。对于发生相同的行为“ 批量插入 ”与
innodb_autoinc_lock_mode=1。表级AUTO-INC锁不用于
innodb_autoinc_lock_mode=2。有关更多信息,请参见
第14.8.1.5节“InnoDB中的AUTO_INCREMENT处理”。
当您重新启动MySQL服务器时,
InnoDB可以重新使用为AUTO_INCREMENT列生成但从未存储的旧值(即在回滚的旧事务期间生成的值)。
当一个AUTO_INCREMENT整数列用完值时,后续INSERT
操作将返回一个重复键错误。这是一般的MySQL行为。
DELETE FROM
不会重新生成表格,而是会逐个删除所有行。
tbl_name
级联外键操作不会激活触发器。
不能创建与内部的名称匹配的列名的表InnoDB列(其中包括DB_ROW_ID,
DB_TRX_ID,
DB_ROLL_PTR,和
DB_MIX_ID)。此限制适用于在任何字母大小写中使用名称。
MySQL的> CREATE TABLE t1 (c1 INT, db_row_id INT) ENGINE=INNODB;
错误1166(42000):错误的列名'db_row_id'
LOCK TABLESinnodb_table_locks=1(默认情况下)在每个表上获取两个锁
。除了MySQL层的InnoDB表锁之外,它还获得表锁。4.1.2之前版本的MySQL没有获取
InnoDB表锁; 旧的行为可以通过设置来选择
innodb_table_locks=0。如果没有
InnoDB获取表锁,LOCK TABLES即使某些表的记录被其他事务锁定,
也会完成。
在MySQL 5.7中,
innodb_table_locks=0对显式锁定的表没有任何影响
LOCK TABLES
... WRITE。它对LOCK TABLES
... WRITE隐式(例如通过触发器)或通过隐式
读取或写入的表有效
LOCK TABLES
... READ。
InnoDB事务持有的
所有锁都在事务提交或中止时释放。因此,它并没有多大意义,调用
LOCK TABLES上
InnoDB表中
autocommit=1模式,因为所获得的InnoDB表锁将被立即释放。
您不能在事务中间锁定其他表,因为LOCK
TABLES它执行隐式
COMMIT和
UNLOCK
TABLES。
数据修改事务的限制是产生撤消记录的96 * 1023个并发事务。将128个回滚段中的32个分配给用于修改临时表和相关对象的事务的非重做日志。这可以将并发数据修改事务的最大数量从128K减少到96K。96K限制假定事务不修改临时表。如果所有数据修改事务也修改临时表,则限制为32K个并发事务。
本节涵盖与InnoDB
索引相关的主题。
每个InnoDB表都有一个称为聚集索引的特殊索引,
其中存储行的数据。通常,聚集索引与主键是同义的
。为了从查询,插入和其他数据库操作中获得最佳性能,您必须了解如何InnoDB
使用聚簇索引来优化每个表的最常见查找和DML操作。
当你PRIMARY KEY在你的表上定义一个时,InnoDB使用它作为聚集索引。为您创建的每个表定义一个主键。如果没有逻辑唯一且非空的列或一组列,请添加一个新的
自动增量
列,其值将自动填入。
如果你没有PRIMARY KEY为你的表定义一个,MySQL将找到UNIQUE所有关键列的第一个
索引,NOT NULL并将
InnoDB它用作聚集索引。
如果该表没有PRIMARY KEY或具有合适的UNIQUE索引,则在
InnoDB内部生成一个隐藏的聚集索引GEN_CLUST_INDEX,该索引在包含行ID值的合成列上命名。这些行按照InnoDB分配给此表中的行的ID进行排序。行ID是一个6字节的字段,随着新行的插入而单调递增。因此,由行ID排序的行在物理上处于插入顺序。
通过聚集索引访问行很快,因为索引搜索直接导向包含所有行数据的页面。如果表很大,与使用与索引记录不同页面存储行数据的存储组织相比,聚簇索引体系结构通常会节省磁盘I / O操作。
除聚集索引以外的所有索引都称为
二级索引。在中InnoDB,辅助索引中的每条记录都包含该行的主键列以及为辅助索引指定的列。
InnoDB使用此主键值搜索聚集索引中的行。
如果主键很长,二级索引使用更多空间,所以有一个短主键是有利的。
有关利用InnoDB
集群索引和二级索引的指导原则,请参见
第8.3节“优化和索引”。
除空间索引外,InnoDB
索引是B树数据结构。空间索引使用
R树,这是用于索引多维数据的专用数据结构。索引记录存储在B树或R树数据结构的叶页中。索引页面的默认大小是16KB。
将新记录插入到InnoDB
聚集索引时,会
InnoDB尝试将页面的1/16空闲以供将来插入和更新索引记录。如果索引记录以连续顺序(升序或降序)插入,则生成的索引页大约为15/16。如果记录以随机顺序插入,则页面从1/2到15/16满。
InnoDB在创建或重建B-tree索引时执行批量加载。这种索引创建方法被称为排序索引构建。该
innodb_fill_factor
配置选项定义的空间作为排序指标构建过程中填充,为今后指数增长预留的剩余空间每个B树页的百分比。空间索引不支持排序索引构建。有关更多信息,请参见第14.8.2.3节“分类索引构建”。一个
innodb_fill_factor100设置叶免费为未来指数增长的聚簇索引页的空间的1/16。
如果InnoDB索引页面的填充因子降到低于MERGE_THRESHOLD默认值(如果未指定时为50%),则InnoDB尝试缩小索引树以释放页面。该
MERGE_THRESHOLD设置适用于B树和R树索引。有关更多信息,请参见
第14.6.13节“为索引页配置合并阈值”。
您可以通过在初始化MySQL实例之前设置配置选项来为MySQL实例中的所有表空间
定义页面大小。一旦定义了实例的页面大小,如果不重新初始化实例,则无法对其进行更改。支持的尺寸是64KB,32KB,16KB(默认),8KB,和4KB,对应于该选项值
,,
,,和
。
InnoDBinnodb_page_size64k32k16k8k4k
在MySQL 5.7中增加了对32KB和64KB页面大小的支持。有关更多信息,请参阅
innodb_page_size文档。
使用特定InnoDB
页面大小的MySQL实例不能使用来自使用不同页面大小的实例的数据文件或日志文件。
InnoDB执行批量加载而不是在创建或重建索引时插入一个索引记录。这种索引创建方法也被称为排序索引构建。空间索引不支持排序索引构建。
索引构建有三个阶段。在第一阶段, 扫描聚集索引,并生成索引条目并将其添加到排序缓冲区。当排序缓冲区变满时,条目将被排序并写出到临时中间文件。这个过程也被称为“ 运行 ”。在第二阶段,将一个或多个运行写入临时中间文件,对文件中的所有条目执行合并排序。在第三阶段和最后阶段,将排序的条目插入 B树中。
在引入排序索引构建之前,使用插入API一次将索引条目插入B树一条记录。此方法涉及打开B树 游标以查找插入位置,然后使用乐观插入将条目插入B树页面 。如果由于页面已满而导致插入失败, 将执行悲观插入操作,这将涉及打开B树光标并根据需要拆分和合并B树节点以查找条目的空间。这种“ 自上而下 ”的弊端在于, 构建索引的方法是搜索插入位置和B树节点的不断拆分和合并的成本。
排序索引构建使用“ 自下而上 ”建立索引的方法。通过这种方法,B树的所有级别都会引用最右边的页面页面。在必要的B树深度处的最右边的页面页被分配并且根据它们的排序顺序插入条目。一旦叶子页面已满,节点指针会附加到父页面上,并为下一个插入页面分配一个兄弟叶页面。该过程继续,直到插入所有条目,这可能导致插入到根级别。当分配兄弟页面时,将释放对先前固定的页面页面的引用,并且新分配的页面页面将成为最右侧的页面页面和新的默认插入位置。
要为未来的索引增长留出空间,可以使用
innodb_fill_factor
配置选项来保留B树页面空间的百分比。例如,innodb_fill_factor在排序索引构建期间,设置
为80保留B树页面中20%的空间。该设置适用于B树叶和非叶页。它不适用于用于TEXT或
BLOB输入的外部页面
。保留的空间量可能与配置不完全相同,因为该
innodb_fill_factor值被解释为提示而非硬限制。
全文索引 支持排序索引构建 。以前,SQL被用来将条目插入到全文索引中。
用于压缩表格,先前的索引创建方法将条目附加到压缩页面和未压缩页面。当修改日志(代表压缩页面上的可用空间)变满时,压缩的页面将被重新压缩。如果由于空间不足而导致压缩失败,页面将被拆分。使用排序索引构建时,条目仅附加到未压缩页面。当一个未压缩的页面变满时,它被压缩。自适应填充用于确保在大多数情况下压缩能够成功,但如果压缩失败,则会拆分页面并再次尝试压缩。这个过程一直持续到压缩成功。有关B-Tree页面压缩的更多信息,请参阅 第14.9.1.5节“InnoDB表的压缩是如何工作的”。
重排日志在排序索引构建过程中被禁用。相反,有一个 检查点可确保索引构建能够承受崩溃或故障。检查点强制将所有脏页写入磁盘。在排序的索引构建期间,页面清理器 线程会定期发送信号以刷新 脏页面,以确保可以快速处理检查点操作。通常,当干净页面数量低于设定阈值时,页面清理器线程会刷新脏页面。对于有序的索引构建,会立即刷新脏页以减少检查点开销并且平行化I / O和CPU活动。
排序索引构建可能会导致 优化器统计信息与先前创建索引方法所生成的统计信息不同。预计不会影响工作负载性能的统计差异是由于用于填充索引的算法不同所致。
FULLTEXT索引是在基于文本的列(CHAR,
VARCHAR或TEXT列)上创建的,
以帮助加快对包含在这些列中的数据的查询和DML操作,省略任何定义为停用词的单词。
甲FULLTEXT指数被定义为一个的一部分
CREATE TABLE说明或使用添加到现有的表ALTER
TABLE或CREATE INDEX。
全文搜索使用MATCH()
... AGAINST语法来执行。有关使用信息,请参见
第12.9节“全文搜索功能”。
InnoDB FULLTEXT 索引在本节中的以下主题下进行介绍:
创建InnoDB
FULLTEXT索引时,会创建一组索引表,如下例所示:
MySQL的>CREATE TABLE opening_lines (id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY,opening_line TEXT(500),author VARCHAR(200),title VARCHAR(200),FULLTEXT idx (opening_line)) ENGINE=InnoDB;MySQL的>SELECT table_id, name, space from INFORMATION_SCHEMA.INNODB_SYS_TABLESWHERE name LIKE 'test/%';+ ---------- + -------------------------------------- -------------- + ------- + | table_id | 名称| 空间| + ---------- + -------------------------------------- -------------- + ------- + | 333 | 测试/ FTS_0000000000000147_00000000000001c9_INDEX_1 | 289 | | 334 | 测试/ FTS_0000000000000147_00000000000001c9_INDEX_2 | 290 | | 335 | 测试/ FTS_0000000000000147_00000000000001c9_INDEX_3 | 291 | | 336 | 测试/ FTS_0000000000000147_00000000000001c9_INDEX_4 | 292 | | 337 | 测试/ FTS_0000000000000147_00000000000001c9_INDEX_5 | 293 | | 338 | 测试/ FTS_0000000000000147_00000000000001c9_INDEX_6 | 294 | | 330 | 测试/ FTS_0000000000000147_BEING_DELETED | 286 | | 331 | 测试/ FTS_0000000000000147_BEING_DELETED_CACHE | 287 | | 332 | 测试/ FTS_0000000000000147_CONFIG | 288 | | 328 | 测试/ FTS_0000000000000147_DELETED | 284 | | 329 | 测试/ FTS_0000000000000147_DELETED_CACHE | 285 | | 327 | test / opening_lines | 283 | + ---------- + -------------------------------------- -------------- + ------- +
前六个表格表示倒排索引,并被称为辅助索引表。当输入文档被标记时,单个词(也称为
“ 标记 ”)与位置信息和相关联的文档ID(DOC_ID)一起被插入到索引表中。基于字的第一个字符的字符集分类权重,字被完全排序并在六个索引表中分区。
倒排索引被分成六个辅助索引表以支持并行索引创建。默认情况下,两个线程将标记,排序并将单词和关联数据插入到索引表中。线程数可以使用该innodb_ft_sort_pll_degree
选项进行配置
。考虑FULLTEXT在大型表上创建索引时增加线程数。
辅助索引表名以前缀FTS_和后缀
为前缀
INDEX_*。每个索引表都通过索引表名称中与table_id索引表匹配的十六进制值与索引表相关联。例如,table_id所述的
test/opening_lines表是
327,为此,十六进制值是0x147。如上例所示,“ 147 ”十六进制值出现在与该test/opening_lines表关联的索引表的名称中。
表示的十六进制值index_id的的FULLTEXT索引也出现在辅助索引表名。例如,在辅助表名称中
test/FTS_0000000000000147_00000000000001c9_INDEX_1,十六进制值1c9的十进制值为457. 可以通过查询
表(457)来确定在opening_lines
表(idx)
上定义的索引INFORMATION_SCHEMA.INNODB_SYS_INDEXES。
MySQL的>SELECT index_id, name, table_id, space from INFORMATION_SCHEMA.INNODB_SYS_INDEXESWHERE index_id=457;+ ---------- + ------ + ---------- + ------- + | index_id | 名称| table_id | 空间| + ---------- + ------ + ---------- + ------- + | 457 | idx | 327 | 283 | + ---------- + ------ + ---------- + ------- +
如果主表是在每个表的文件表 空间中创建的,则索引表将存储在其自己 的表空间中。
上例中显示的其他索引表称为公共索引表,用于删除处理和存储FULLTEXT索引的内部状态
。与为每个全文索引创建的倒排索引表不同,这组表对于在特定表上创建的所有全文索引都是通用的。
即使全文索引被删除,通用辅助表也会被保留。删除全文索引时,
FTS_DOC_ID保留为索引创建的FTS_DOC_ID列,因为删除
列需要重建表。管理FTS_DOC_ID色谱柱需要共同的腋窝表
。
FTS_*_DELETED 和
FTS_*_DELETED_CACHE
包含已删除但其数据尚未从全文索引中删除的文档的文档ID(DOC_ID)。这
FTS_*_DELETED_CACHE是该FTS_*_DELETED表的内存中版本。
FTS_*_BEING_DELETED 和
FTS_*_BEING_DELETED_CACHE
包含已删除文档的文档ID(DOC_ID),其数据当前正在从全文索引中删除。该FTS_*_BEING_DELETED_CACHE表是该
表的内存中版本
FTS_*_BEING_DELETED。
FTS_*_CONFIG
存储有关FULLTEXT索引内部状态的信息
。最重要的是,它存储了FTS_SYNCED_DOC_ID标识已被分析并刷新到磁盘的文档。在崩溃恢复的情况下,
FTS_SYNCED_DOC_ID值用于标识尚未刷新到磁盘的文档,以便可以重新解析文档并将其添加回
FULLTEXT索引缓存。要查看此表中的数据,请查询该
INFORMATION_SCHEMA.INNODB_FT_CONFIG
表。
插入文档时,会将其标记,并将单个词和关联的数据插入到
FULLTEXT索引中。即使对于小文档,这个过程可能导致大量的小插入到辅助索引表中,使得这些表的并发访问成为争用点。为避免此问题,请
InnoDB使用FULLTEXT
索引缓存临时缓存最近插入的行的索引表插入。这个内存中的缓存结构持有插入,直到缓存满了,然后将它们批量刷新到磁盘(到辅助索引表)。您可以查询该
INFORMATION_SCHEMA.INNODB_FT_INDEX_CACHE
表以查看最近插入的行的标记化数据。
缓存和批量刷新行为避免了对辅助索引表的频繁更新,这可能会导致在繁忙的插入和更新时间期间出现并发访问问题。批处理技术还避免了同一单词的多次插入,并最大限度地减少了重复条目。不是单独刷新每个单词,而是将同一单词的插入作为单个条目合并并刷新到磁盘,从而提高插入效率,同时保持辅助索引表尽可能小。
该innodb_ft_cache_size
变量用于配置全文索引缓存大小(基于每个表),这会影响刷新全文索引缓存的频率。您还可以使用该innodb_ft_total_cache_size
选项为给定实例中的所有表定义全局全文索引缓存大小限制
。
全文索引缓存存储与辅助索引表相同的信息。但是,全文索引缓存仅缓存最近插入的行的标记化数据。查询时,已经刷新到磁盘(到全文辅助表)的数据不会被带回到全文索引缓存中。辅助索引表中的数据直接被查询,并且辅助索引表中的结果与返回前的全文索引缓存的结果合并。
InnoDB使用称为文档ID(DOC_ID)的唯一文档标识符将全文索引中的单词映射到出现该单词的文档记录。该映射需要FTS_DOC_ID索引表上的一
列。如果FTS_DOC_ID未定义
列,则在创建全文索引时InnoDB自动添加隐藏
FTS_DOC_ID列。以下示例演示了此行为。
下表定义不包括一
FTS_DOC_ID列:
MySQL的>CREATE TABLE opening_lines (id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY,opening_line TEXT(500),author VARCHAR(200),title VARCHAR(200)) ENGINE=InnoDB;
当您使用CREATE FULLTEXT INDEX语法在表上创建全文索引时,将
返回一个警告,报告InnoDB重建表以添加该FTS_DOC_ID
列。
MySQL的>CREATE FULLTEXT INDEX idx ON opening_lines(opening_line);查询OK,0行受影响,1个警告(0.19秒) 记录:0重复:0警告:1 MySQL的>SHOW WARNINGS;+ --------- + ------ + -------------------------------- ------------------ + | 级别| 代码| 留言| + --------- + ------ + -------------------------------- ------------------ + | 警告| 124 | InnoDB重建表添加列FTS_DOC_ID | + --------- + ------ + -------------------------------- ------------------ +
使用ALTER TABLE将全文索引添加到没有FTS_DOC_ID列的表时,会
返回相同的警告
。如果您在CREATE TABLE
时间创建全文索引并且未指定FTS_DOC_ID
列,请InnoDB添加隐藏
FTS_DOC_ID列,而不发出警告。
FTS_DOC_ID在CREATE TABLE时间上
定义列
比在已经加载数据的表上创建全文索引便宜。如果FTS_DOC_ID
在加载数据之前在表上定义列,则不必重建表及其索引以添加新列。如果您不关注CREATE FULLTEXT
INDEX性能,请忽略该
FTS_DOC_ID列
InnoDB以为您创建它。
InnoDB创建一个隐藏的
FTS_DOC_ID列以及FTS_DOC_ID_INDEX该FTS_DOC_ID列上唯一的索引()
。如果您想创建自己的FTS_DOC_ID列,则该列必须被定义为BIGINT UNSIGNED NOT NULL并命名FTS_DOC_ID (全部大写),如下例所示:
该FTS_DOC_ID列不需要定义为AUTO_INCREMENT列,但
AUTO_INCREMENT可以使加载数据更容易。
MySQL的>CREATE TABLE opening_lines (FTS_DOC_ID BIGINT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY,opening_line TEXT(500),author VARCHAR(200),title VARCHAR(200)) ENGINE=InnoDB;
如果您选择自己定义FTS_DOC_ID
列,则负责管理列以避免空值或重复值。
FTS_DOC_ID值不能被重用,这意味着FTS_DOC_ID值必须不断增加。
或者,您可以FTS_DOC_ID_INDEX在FTS_DOC_ID列上创建所需的唯一
(全部大写)
。
MySQL的> CREATE UNIQUE INDEX FTS_DOC_ID_INDEX on opening_lines(FTS_DOC_ID);
如果你不创建FTS_DOC_ID_INDEX,
InnoDB自动创建它。
在MySQL 5.7.13之前,最大使用FTS_DOC_ID值和新
FTS_DOC_ID值之间的允许差距为10000.在MySQL 5.7.13和更高版本中,允许的差距为65535。
为了避免重建表格,FTS_DOC_ID在删除全文索引时保留该
列。
删除具有全文索引列的记录可能会导致辅助索引表中的许多小的删除操作,从而使这些表的并发访问成为争用点。为避免此问题,每当从索引表中删除DOC_ID记录时,已删除文档的文档ID()都会记录在特殊FTS_*_DELETED表中,并且索引记录保留在全文索引中。在返回查询结果之前,FTS_*_DELETED
表用于过滤掉已删除的文档ID。这种设计的好处是删除速度快而且价格低廉。缺点是在删除记录后索引的大小不会立即减小。要删除已删除记录的全文索引条目,请OPTIMIZE
TABLE在索引表上
运行innodb_optimize_fulltext_only=ON
以重建全文索引。有关更多信息,请参阅
优化InnoDB全文索引。
InnoDB FULLTEXT由于缓存和批处理行为,索引具有特殊的事务处理特性。具体而言,FULLTEXT在事务提交时处理索引上的更新和插入,这意味着
FULLTEXT搜索只能看到已提交的数据。以下示例演示了此行为。该
FULLTEXT搜索只返回插入的行被提交之后的结果。
MySQL的>CREATE TABLE opening_lines (id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY,opening_line TEXT(500),author VARCHAR(200),title VARCHAR(200),FULLTEXT idx (opening_line)) ENGINE=InnoDB;MySQL的>BEGIN;MySQL的>INSERT INTO opening_lines(opening_line,author,title) VALUES('Call me Ishmael.','Herman Melville','Moby-Dick'),('A screaming comes across the sky.','Thomas Pynchon','Gravity\'s Rainbow'),('I am an invisible man.','Ralph Ellison','Invisible Man'),('Where now? Who now? When now?','Samuel Beckett','The Unnamable'),('It was love at first sight.','Joseph Heller','Catch-22'),('All this happened, more or less.','Kurt Vonnegut','Slaughterhouse-Five'),('Mrs. Dalloway said she would buy the flowers herself.','Virginia Woolf','Mrs. Dalloway'),('It was a pleasure to burn.','Ray Bradbury','Fahrenheit 451');MySQL的>SELECT COUNT(*) FROM opening_lines WHERE MATCH(opening_line) AGAINST('Ishmael');+ ---------- + | COUNT(*)| + ---------- + | 0 | + ---------- + MySQL的>COMMIT;MySQL的>SELECT COUNT(*) FROM opening_lines WHERE MATCH(opening_line) AGAINST('Ishmael');+ ---------- + | COUNT(*)| + ---------- + | 1 | + ---------- +
您可以InnoDB
FULLTEXT通过查询以下INFORMATION_SCHEMA表格来监视和检查索引
的特殊文本处理方面:
您还可以FULLTEXT通过查询INNODB_SYS_INDEXES和
查看索引和表格的
基本信息
INNODB_SYS_TABLES。
有关更多信息,请参见 第14.15.4节“InnoDB INFORMATION_SCHEMA全文索引表”。
本节提供有关
InnoDB表压缩和
InnoDB页面压缩功能的信息。页面压缩功能被称为
透明页面压缩。
使用压缩功能InnoDB,您可以创建表格,以压缩形式存储数据。压缩有助于提高原始性能和可扩展性。压缩意味着更少的数据在磁盘和内存之间传输,并且占用磁盘和内存中的更少空间。对于具有二级索引的表格,这些好处会被放大
,因为索引数据也会被压缩。压缩对于SSD存储设备尤其重要,因为它们的容量往往低于
HDD设备。
本节介绍InnoDB表压缩,该表压缩由InnoDB
驻留在
file_per_table
表空间或常规表空间中的表支持。表压缩通过使用or
的ROW_FORMAT=COMPRESSED属性
来启用
。
CREATE TABLEALTER TABLE
由于处理器和缓存内存的速度比磁盘存储设备的速度提高得多,因此许多工作负载都是 磁盘绑定的。数据 压缩能够实现更小的数据库大小,减少I / O并提高吞吐量,同时以较少的CPU利用率提高成本。对于读密集型应用程序而言,压缩尤其有价值,因为系统具有足够的RAM以将频繁使用的数据保存在内存中。
InnoDB创建
的表
ROW_FORMAT=COMPRESSED可以在磁盘上使用比配置
值小的
页面大小innodb_page_size。较小的页面需要较少的I / O读取和写入磁盘,这对SSD设备特别有用
。
压缩的页面大小通过CREATE TABLE或
参数指定
。由于系统表空间不能存储压缩表,因此不同的页面大小要求将表放置在
每个表文件的文件表
空间或常规表空间中,而不是放在
系统表空间中。有关更多信息,请参见
第14.7.4节“InnoDB每个表文件的表空间”和
第14.7.9节“InnoDB常规表空间”。
ALTER TABLE
KEY_BLOCK_SIZE
不管KEY_BLOCK_SIZE值如何,压缩级别都是相同的
。当您指定较小的值时KEY_BLOCK_SIZE,您可以获得越来越小页面的I / O优势。但是,如果您指定的值太小,则当数据值无法压缩到足以适应每个页面中的多行时,会有额外的开销来重新组织页面。KEY_BLOCK_SIZE根据每个索引的键列长度,对于表格的小小可以有一个严格限制。指定值过小,
CREATE TABLE或
ALTER TABLE语句失败。
在缓冲池中,压缩数据保存在小页面中,页面大小基于该KEY_BLOCK_SIZE
值。为了提取或更新列值,MySQL还使用未压缩的数据在缓冲池中创建一个未压缩的页面。在缓冲池中,对未压缩页面的任何更新也会重新写回等效的压缩页面。您可能需要调整缓冲池的大小以适应压缩和未压缩页面的额外数据,尽管未压缩的页面在
需要空间时从缓冲池中逐出,然后在下次访问时再次解压缩。
压缩表可以在 每个表的文件表 空间或 一般的表空间中创建。表压缩不适用于InnoDB 系统表空间。系统表空间(空间0, .ibdata文件)可以包含用户创建的表,但它也包含内部系统数据,这些数据从不压缩。因此,压缩仅适用于存储在每个文件或一般表空间中的表(和索引)。
要在每个表的文件表空间中创建压缩表,
innodb_file_per_table必须启用(MySQL 5.6.6中的默认innodb_file_format设置)并且
必须设置为Barracuda。您可以使用
语句在MySQL配置文件(my.cnf或
my.ini)中或动态地
设置这些参数SET。
在配置innodb_file_per_table
和innodb_file_format选项后,在a 或
语句中指定
ROW_FORMAT=COMPRESSED子句或
KEY_BLOCK_SIZE子句或两者,以
在每个文件表的表空间中创建一个压缩表。
CREATE TABLEALTER TABLE
例如,您可以使用以下语句:
SET GLOBAL innodb_file_per_table = 1; SET GLOBAL innodb_file_format =梭鱼; 创建表t1 (c1 INT主键) ROW_FORMAT = COMPRESSED KEY_BLOCK_SIZE = 8;
要在常规表空间中创建压缩表,
FILE_BLOCK_SIZE必须为创建表空间时指定的常规表空间定义。该FILE_BLOCK_SIZE值必须是与该值相关的有效压缩页面大小
innodb_page_size,并且由CREATE TABLEor
子句定义的压缩表的页面大小
必须等于
。例如,如果
和
,
表的值必须为8.有关更多信息,请参见第14.7.9节“InnoDB常规表空间”。
ALTER TABLE
KEY_BLOCK_SIZEFILE_BLOCK_SIZE/1024innodb_page_size=16384FILE_BLOCK_SIZE=8192KEY_BLOCK_SIZE
以下示例演示如何创建常规表空间并添加压缩表。该示例假设默认
innodb_page_size值为16K。在
FILE_BLOCK_SIZE8192要求压缩表有KEY_BLOCK_SIZE8个。
MySQL的>CREATE TABLESPACE `ts2` ADD DATAFILE 'ts2.ibd' FILE_BLOCK_SIZE = 8192 Engine=InnoDB;MySQL的>CREATE TABLE t4 (c1 INT PRIMARY KEY) TABLESPACE ts2 ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=8;
如果你指定ROW_FORMAT=COMPRESSED,你可以省略KEY_BLOCK_SIZE; 该
KEY_BLOCK_SIZE设置默认为innodb_page_size值的一半。
如果您指定了有效的KEY_BLOCK_SIZE
值,则可以省略
ROW_FORMAT=COMPRESSED; 压缩自动启用。
要确定最佳值,
KEY_BLOCK_SIZE,通常可以为此子句创建具有不同值的同一表的多个副本,然后测量结果.ibd文件的大小,并查看每个副本对于
实际工作负载的执行情况
。对于常规表空间,请记住,删除表不会减小常规表空间.ibd文件的大小
,也不会将磁盘空间返回给操作系统。有关更多信息,请参见
第14.7.9节“InnoDB常规表空间”。
该KEY_BLOCK_SIZE值被视为提示; InnoDB如果需要,可以使用不同的尺寸
。对于每个文件表的表空间,KEY_BLOCK_SIZE只能小于或等于该
innodb_page_size值。如果指定的值大于该
innodb_page_size值,则会忽略指定的值,发出警告,并将
KEY_BLOCK_SIZE其设置为该innodb_page_size值的一半
。如果
innodb_strict_mode=ON指定一个无效KEY_BLOCK_SIZE值会返回一个错误。对于一般的表空间,有效值
KEY_BLOCK_SIZE取决于FILE_BLOCK_SIZE表空间的
设置。有关更多信息,请参阅
第14.7.9节“InnoDB常规表空间”。
32k和64k页面大小不支持压缩。有关更多信息,请参阅
innodb_page_size
文档。
InnoDB
数据页面
的默认未压缩大小为16KB。根据选项值的组合,MySQL为表空间数据文件(.ibd文件)使用1KB,2KB,4KB,8KB或16KB的页面大小。实际的压缩算法不受该KEY_BLOCK_SIZE值的影响
; 该值确定每个压缩块有多大,这反过来又影响可以将每行压缩到每个压缩页中的行数。
在每个文件表的表空间中创建压缩表时,设置KEY_BLOCK_SIZE等于InnoDB
页面大小通常不会导致太多的压缩。例如,
KEY_BLOCK_SIZE=16由于正常InnoDB页面大小为16KB ,因此通常不会导致太多压缩
。此设置可能仍然是许多长条桌有用的
BLOB,
VARCHAR或
TEXT列,因为这种价值观往往压缩得很好,因此可能需要较少的溢出页中描述
第14.9.1.5,“如何压缩适用于InnoDB表”。对于一般的表空间,不允许有KEY_BLOCK_SIZE等于InnoDB页面大小的值。有关更多信息,请参见
第14.7.9节“InnoDB常规表空间”。
表(包括聚集索引)的所有索引
都使用与CREATE TABLEor ALTER
TABLE语句中指定的相同页面大小进行压缩
。表格属性(如
ROW_FORMAT和)
KEY_BLOCK_SIZE不是表格CREATE INDEX语法的
一部分
InnoDB,如果指定它们(如果指定,它们将出现在SHOW CREATE
TABLE语句的输出中)将被忽略。
有关与性能相关的配置选项,请参见 第14.9.1.3节“调整InnoDB表的压缩”。
5.1之前的MySQL版本无法处理压缩表。
压缩的表不能存储在
InnoDB系统表空间中。
常规表空间可以包含多个表,但是压缩和未压缩的表不能共存于同一个通用表空间中。
压缩适用于整个表及其所有关联索引,而不适用于单个行,尽管使用了子句名称ROW_FORMAT。
InnoDB数据存储和压缩中 描述的内部优化通常会 确保系统在压缩数据下运行良好。但是,由于压缩效率取决于数据的性质,因此可以制定影响压缩表性能的决策:
使用本节中的准则来帮助进行这些架构和配置选择。当您准备好进行长期测试并将压缩表投入生产时,请参见 第14.9.1.4节“在运行时监控InnoDB表压缩”,了解验证这些选择在真实条件下的有效性的方法。
一般来说,压缩在包含合理数量的字符串列的表上工作得最好,并且数据读取的次数比写入的次数要多得多。因为没有可靠的方法来预测压缩是否有利于特定情况,所以请始终使用代表性配置上运行的特定工作负载和数据集进行测试 。决定要压缩哪些表时请考虑以下因素。
数据文件大小压缩效率的关键决定因素是数据本身的性质。回想一下,压缩的工作原理是通过识别数据块中的重复字节串。完全随机数据是最糟糕的情况。典型的数据通常具有重复的值,因此有效地压缩。字符串经常压缩得很好,在是否定义CHAR,VARCHAR,
TEXT或BLOB列。另一方面,主要包含二进制数据(整数或浮点数)或先前压缩的数据(例如JPEG或PNG
图像)的表格通常可能无法很好地压缩,显着或根本不压缩。
您可以选择是否为每个InnoDB表打开压缩。表及其所有索引使用相同(压缩)的 页面大小。主键 (聚集)索引可能比二级索引更有效地压缩,其中包含表中所有列的数据。对于存在长行的情况,使用压缩可能导致长列值被存储为 “ 离页 ”,如 第14.11.3节“动态和压缩行格式”中所述。。这些溢出页面可能压缩得很好。鉴于这些考虑因素,对于许多应用程序,某些表比其他表压缩更有效,并且您可能会发现只有压缩表的子集才能使工作负载表现最佳。
要确定是否要压缩某个表,请进行实验。您可以粗略地估算一下,如何通过在未压缩表gzip的.ibd文件的副本上使用实现LZ77压缩的实用程序(如WinZip)来压缩数据的效率。您可以期望从MySQL压缩表压缩比从基于文件的压缩工具更少的压缩,因为MySQL根据页面大小压缩数据块,默认为16KB。除用户数据外,页面格式还包括一些未压缩的内部系统数据。基于文件的压缩实用程序可以检查更大的数据块,因此可能会在MySQL文件中找到的大文件中找到更多重复的字符串。
在特定表上测试压缩的另一种方法是将一些数据从未压缩的表中复制到每个文件表的表
空间中类似的压缩表(具有所有相同的索引),
并查看生成.ibd文件的大小
。例如:
USE测试; SET GLOBAL innodb_file_per_table = 1; SET GLOBAL innodb_file_format =梭鱼; SET GLOBAL autocommit = 0; - 创建一个具有一百或两行的未压缩表。 CREATE TABLE big_table AS SELECT * FROM information_schema.columns; INSERT INTO big_table SELECT * FROM big_table; INSERT INTO big_table SELECT * FROM big_table; INSERT INTO big_table SELECT * FROM big_table; INSERT INTO big_table SELECT * FROM big_table; INSERT INTO big_table SELECT * FROM big_table; INSERT INTO big_table SELECT * FROM big_table; INSERT INTO big_table SELECT * FROM big_table; INSERT INTO big_table SELECT * FROM big_table; INSERT INTO big_table SELECT * FROM big_table; INSERT INTO big_table SELECT * FROM big_table; 承诺; ALTER TABLE big_table ADD id int unsigned NOT NULL PRIMARY KEY auto_increment; SHOW CREATE TABLE big_table \ G 从big_table中选择count(id); - 检查未压缩表格需要多少空间。 \!ls -l data / test / big_table.ibd CREATE TABLE key_block_size_4 LIKE big_table; ALTER TABLE key_block_size_4 key_block_size = 4 row_format = compressed; INSERT INTO key_block_size_4 SELECT * FROM big_table; 承诺; - 检查压缩表需要多少空间 - 使用特定的压缩设置。 \!ls -l data / test / key_block_size_4.ibd
这个实验产生了下面的数字,这当然会根据你的表格结构和数据而有很大的不同:
-rw-rw ---- 1卷绕工作人员310378496 Jan 9 13:44 data / test / big_table.ibd -rw-rw ---- 1卷绕工作人员83886080 Jan 9 15:10 data / test / key_block_size_4.ibd
要查看压缩对于您的特定工作负载是否有效 :
对于简单的测试,使用没有其他压缩表的MySQL实例并针对该INFORMATION_SCHEMA.INNODB_CMP
表运行查询
。
有关包含具有多个压缩表的工作负载的更详细测试,请针对该INFORMATION_SCHEMA.INNODB_CMP_PER_INDEX
表运行查询
。由于INNODB_CMP_PER_INDEX表中的统计信息
收集起来很昂贵,因此必须innodb_cmp_per_index_enabled
在查询该表之前启用配置选项
,并且可以将这些测试限制在开发服务器或非关键的
从服务器上。
对正在测试的压缩表运行一些典型的SQL语句。
通过查询检查成功压缩操作,以整体的压缩操作的比率
INFORMATION_SCHEMA.INNODB_CMP
或
INFORMATION_SCHEMA.INNODB_CMP_PER_INDEX
表,并且比较COMPRESS_OPS向
COMPRESS_OPS_OK。
如果高比例的压缩操作成功完成,则表格可能是压缩的理想选择。
如果压缩失败的比例较高
,可以
按照第14.9.1.6节“OLTP工作负载的压缩”中所述调整
innodb_compression_level,
innodb_compression_failure_threshold_pct和
innodb_compression_pad_pct_max选项
,然后尝试进一步测试。
决定是否压缩应用程序或表中的数据; 请勿对同一数据使用两种类型的压缩。当您在应用程序中压缩数据并将结果存储在压缩表中时,极其不可能节省额外的空间,而双重压缩只会浪费CPU周期。
启用时,MySQL表压缩是自动的,适用于所有列和索引值。LIKE即使索引值被压缩,仍然可以使用运算符(例如,)对列进行测试,并且排序操作仍然可以使用索引。由于索引通常占数据库总大小的很大一部分,因此压缩可能会显着节省存储空间,I / O或处理器时间。压缩和解压缩操作发生在数据库服务器上,这可能是一个处理预期负载的功能强大的系统。
如果在应用程序中压缩数据(例如文本),然后将其插入数据库中,则可以通过压缩某些列而不是压缩某些列来节省数据压缩的开销。这种方法在客户端机器上使用CPU周期进行压缩和解压缩,而非数据库服务器,这可能适用于拥有多个客户端的分布式应用程序,或客户端计算机具有空闲CPU周期的情况。
当然,可以将这些方法结合起来。对于某些应用程序,可能适合使用一些压缩表和一些未压缩的表。最好从外部压缩一些数据(并将其存储在未压缩的表中),并允许MySQL压缩(某些)应用程序中的其他表。与往常一样,前期设计和实际测试对于做出正确的决定是有价值的。
除了选择要压缩的表格(以及页面大小)之外,工作负载还是性能的另一个关键决定因素。如果应用程序由读取操作而非更新操作占据主导地位,那么在索引页空间不足以满足MySQL为压缩数据维护的每页“ 修改日志 ”之后,需要重新组织和重新压缩页面。如果更新主要更改非索引列或包含BLOBs或大字符串的那些恰好存储为“ 脱离页面 ”的列,则压缩的开销可能是可接受的。如果唯一的变化是表格INSERTs使用单调递增的主键,并且二级索引很少,因此很少需要重新组织和重新压缩索引页。由于MySQL能够“ 删除标记 ”,并删除压缩的页面行“ 到位 ”通过修改未压缩的数据,DELETE在表上的操作都比较高效。
对于某些环境,加载数据所需的时间与运行时检索一样重要。特别是在数据仓库环境中,许多表可能是只读的或只读的。在这种情况下,在增加加载时间方面支付压缩的价格可能会也可能不会被接受,除非节省更少的磁盘读取或存储成本是显着的。
基本上,当CPU时间可用于压缩和解压缩数据时,压缩效果最佳。因此,如果您的工作负载受I / O限制,而不是CPU限制,则可能会发现压缩可以提高整体性能。当您使用不同的压缩配置测试应用程序性能时,请在类似于生产系统计划配置的平台上进行测试。
从磁盘 读写数据库 页面是系统性能最慢的一个方面。压缩尝试通过使用CPU时间来压缩和解压缩数据来减少I / O,并且当I / O与处理器周期相比是相对稀缺的资源时最为有效。
在具有快速多核CPU的多用户环境中运行时,情况尤其如此。当压缩表的页面在内存中时,MySQL通常在缓冲池中使用额外的内存(通常为16KB)来存储 页面的未压缩副本。自适应LRU算法试图平衡压缩和未压缩页面之间的内存使用情况,以考虑工作负载是以I / O绑定还是CPU绑定的方式运行。尽管如此,具有更多专用于缓冲池的内存的配置在使用压缩表时比使用高度受限内存的配置更好。
压缩页面大小的最佳设置取决于表及其索引所包含数据的类型和分布。压缩的页面大小应该始终大于最大记录大小,否则操作可能会失败,如 “B-Tree页面的压缩”中所述。
将压缩的页面尺寸设置得太大会浪费一些空间,但页面不必经常压缩。如果压缩的页面大小设置得太小,则插入或更新可能需要耗费时间的重新压缩,并且 B树节点可能不得不更频繁地分割,导致更大的数据文件和更低效的索引。
通常,您将压缩的页面大小设置为8K或4K字节。鉴于InnoDB表的最大行大小约为8K,KEY_BLOCK_SIZE=8通常是安全的选择。
总体应用程序性能,CPU和I / O利用率以及磁盘文件的大小是有效压缩对您的应用程序的有效指标。本节基于第14.9.1.3节“调整InnoDB表的压缩”中的性能调整建议 ,并展示如何查找在初始测试期间可能不会出现的问题。
要深入了解压缩表的性能注意事项,可以使用例14.1“使用压缩信息模式表”中介绍的信息模式表 监视压缩表的运行时压缩性能。这些表格反映了内存的内部使用和整体使用的压缩率。
该INNODB_CMP表报告有关使用中的每个压缩页面大小(KEY_BLOCK_SIZE)的压缩活动的信息。这些表中的信息是系统范围的:它汇总了数据库中所有压缩表的压缩统计信息。您可以使用此数据来帮助您决定是否在没有其他压缩表正在访问时通过检查这些表来压缩表。它在服务器上的开销相对较低,因此您可能会定期在生产服务器上查询它以检查压缩功能的整体效率。
该INNODB_CMP_PER_INDEX表报告有关各个表和索引的压缩活动的信息。此信息对于评估压缩效率和一次诊断一个表或索引的性能问题更有针对性和更有用。(因为每个InnoDB表都被表示为一个聚簇索引,所以MySQL在这种情况下并没有在表和索引之间做出很大的区分。)该
INNODB_CMP_PER_INDEX表确实涉及大量开销,所以它更适合于开发服务器,您可以在其中比较效果不同的工作量,数据和压缩设置。为防止意外强加这种监视开销,必须先启用
innodb_cmp_per_index_enabled
配置选项,然后才能查询
INNODB_CMP_PER_INDEX表。
要考虑的关键统计数据是执行压缩和解压缩操作所需的时间和数量。由于
当B-tree节点太满而无法包含修改后的压缩数据时,它会分割B-tree节点,因此比较
“ 成功 ”压缩操作的数量和整体操作的数量。基于信息
INNODB_CMP和
INNODB_CMP_PER_INDEX 表和整体应用程序性能以及硬件资源利用率,您可以对硬件配置进行更改,调整缓冲池的大小,选择不同的页面大小,或者选择一组不同的表来进行压缩。
如果压缩和解压缩所需的CPU时间很长,则更改为更快或多核的CPU可帮助用相同的数据,应用程序工作负载和一组压缩表提高性能。增加缓冲池的大小也可能有助于提高性能,以便更多未压缩的页面可以保留在内存中,从而减少仅以压缩形式解压缩存在于内存中的页面的需要。
大量的整体压缩操作(与数量INSERT,
UPDATE并DELETE
在您的应用程序操作和数据库的大小)可能表明你的一些压缩的表都被更新过重的有效压缩。如果是这样,请选择一个更大的页面大小,或者选择要压缩的表格。
如果“ 成功 ”压缩操作(COMPRESS_OPS_OK)的数量占压缩操作总数的很高百分比(COMPRESS_OPS),那么系统可能表现良好。如果这个比例很低,那么MySQL正在重组,重新压缩和分割B树节点的次数往往比预期的要多。在这种情况下,避免压缩一些表,或者增加KEY_BLOCK_SIZE一些压缩表。您可以关闭导致“ 压缩失败 ”数量的表的压缩在你的申请中超过1%或2%。(在诸如数据加载的临时操作期间,这样的故障率可能是可接受的)。
本节介绍有关InnoDB表压缩的一些内部实现细节。这里介绍的信息可能有助于调整性能,但不需要知道压缩的基本用法。
某些操作系统在文件系统级别实施压缩。文件通常分成固定大小的块,压缩成可变大小的块,这很容易导致碎片化。每次修改块内的某个内容时,整个块都会在写入磁盘之前被重新压缩。这些属性使这种压缩技术不适合在更新密集型数据库系统中使用。
MySQL在着名的zlib库的帮助下 实现了压缩,它实现了LZ77压缩算法。这种压缩算法在CPU利用率和数据大小的减少方面都是成熟,稳健和高效的。该算法是 “ 无损 ”的,因此原始未压缩数据总是可以从压缩格式重建。LZ77压缩的工作方式是查找要压缩的数据中重复的数据序列。数据中值的模式决定了它压缩的程度,但典型的用户数据通常会压缩50%或更多。
InnoDB zlib仅支持1.2.3版本的库。
与应用程序执行的压缩或某些其他数据库管理系统的压缩功能不同,InnoDB压缩既适用于用户数据,也适用于索引。在许多情况下,索引可以占数据库总大小的40-50%或更多,因此这种差异是显着的。当数据集的压缩效果良好时,InnoDB数据文件(
文件 - 每表表
空间或常规表空间 .idb文件)的大小是未压缩大小的25%到50%,或者可能更小。取决于
工作量,这个较小的数据库可以反过来导致I / O的减少和吞吐量的增加,而对于CPU利用率的增加而言成本适中。您可以通过修改innodb_compression_level
配置选项来调整压缩级别和CPU开销之间的平衡
。
InnoDB表中的所有用户数据都存储在包含 B树索引( 聚簇索引)的页面中。在其他一些数据库系统中,这种类型的索引称为 “ 索引组织表 ”。索引节点中的每一行都包含(用户指定的或系统生成的) 主键和表中所有其他列的值。
InnoDB表中的次级索引也是B树,包含值对:索引键和聚集索引中行的指针。指针实际上是表的主键值,如果需要除索引键和主键以外的列,则该键用于访问聚集索引。二级索引记录必须始终适合单个B树页面。
B-树节点的压缩(的集群和二级索引)是从压缩处理方式不同
溢出页用于存储长VARCHAR,BLOB或TEXT列,如在以下部分中说明。
由于它们经常更新,所以B树页面需要特殊处理。将B树节点拆分的次数最小化以及将解压缩和重新压缩其内容的需求降至最低是非常重要的。
MySQL使用的一种技术是以未压缩的形式维护B树节点中的一些系统信息,从而便于某些就地更新。例如,这允许在没有任何压缩操作的情况下对行进行删除标记和删除。
另外,MySQL试图在更改索引页时避免不必要的解压缩和重新压缩索引页。在每个B-tree页面中,系统保留一个未压缩的 “ 修改日志 ”来记录对页面所做的更改。小记录的更新和插入可写入此修改日志而不需要整个页面被完全重构。
当修改日志的空间用完时,InnoDB解压页面,应用更改并重新压缩页面。如果再压缩失败(称为一个的情况 压缩破坏),B-树节点被分割,并重复该过程,直到更新或插入成功。
为避免写密集型工作负载(如OLTP
应用程序)频繁出现压缩失败,MySQL有时会在页面中保留一些空白区域(填充),以便修改日志尽早填满,页面重新压缩,同时仍有足够空间避免分裂它。随着系统跟踪页面拆分的频率,每个页面中留下的填充空间量也会变化。在频繁写入压缩表的繁忙服务器上,您可以调整
innodb_compression_failure_threshold_pct和
innodb_compression_pad_pct_max
配置选项来微调此机制。
通常,MySQL要求InnoDB表中的每个B树页面至少可以容纳两条记录。对于压缩表,这个要求已经放宽。B树节点的叶页(无论是主键还是二级索引)只需要容纳一条记录,但该记录必须以非压缩形式适合每页修改日志。如果
innodb_strict_mode是
ON,MySQL在CREATE TABLE或
期间检查最大行大小
CREATE INDEX。如果该行不合适,则发出以下错误消息:ERROR
HY000: Too big row。
如果您在innodb_strict_modeOFF 时创建表
,并且随后的INSERTor
UPDATE语句尝试创建不符合压缩页大小的索引条目,则操作将失败,并显示ERROR 42000: Row size too
large。(此错误消息不会为记录太大的索引命名,或者提及索引记录的长度或特定索引页上的最大记录大小。)要解决此问题,请使用重建表
ALTER TABLE并选择更大压缩页面大小(KEY_BLOCK_SIZE),缩短任何列前缀索引,或完全禁用压缩ROW_FORMAT=DYNAMIC或
ROW_FORMAT=COMPACT。
innodb_strict_mode不适用于也支持压缩表的常规表空间。通用表空间的表空间管理规则是独立于,严格执行的
innodb_strict_mode。有关更多信息,请参见第13.1.19节“CREATE TABLESPACE语法”。
在一个InnoDB表,BLOB,
VARCHAR,和
TEXT列不属于主键的一部分可以被存储在单独分配
溢出页。我们将这些列称为
离页列。它们的值存储在单个链接的溢出页面列表中。
在创建的表ROW_FORMAT=DYNAMIC或
ROW_FORMAT=COMPRESSED,的值
BLOB,
TEXT或
VARCHAR列可以取决于它们的长度和整个行的长度存储完全关闭页。对于存储在页外的列,聚簇索引记录仅包含指向溢出页面的20字节指针,每列一个。是否有任何列存储在页外,取决于页面大小和行的总大小。当行太长而无法完全适应聚簇索引的页面时,MySQL会选择离页存储的最长列,直到该行适合聚集索引页面为止。如上所述,如果某行在压缩页面上不适合自身,则会发生错误。
在旧版本的MySQL中创建的表使用
Antelope文件格式,它仅支持ROW_FORMAT=REDUNDANT和
ROW_FORMAT=COMPACT。在这些格式中,MySQL存储第一768个字节的
BLOB,
VARCHAR和
TEXT列在聚集索引记录与主密钥一起。768字节的前缀后跟一个20字节的指针,指向溢出页面,其中包含列值的其余部分。
当一个表格处于COMPRESSED格式时,写入溢出页面的所有数据都会“ 按原样 ”压缩; 也就是说,MySQL将zlib压缩算法应用于整个数据项。除数据以外,压缩溢出页面还包含一个未压缩的标题和尾部,其中包含页面校验和和下一个溢出页面的链接等。因此,能够更长时间来获得非常显著存储节省
BLOB,TEXT或
VARCHAR列如果数据是高度可压缩,这是常有的文本数据的情况。图像数据,如JPEG通常已经被压缩,因此不会从被存储在压缩表中获益; 双倍压缩可能会浪费CPU周期,从而节省很少的空间或不节省空间
溢出页面与其他页面大小相同。包含存储在页外的10列的行占用10个溢出页面,即使列的总长度仅为8K字节。在未压缩的表中,十个未压缩的溢出页占用160K字节。在页面大小为8K的压缩表中,它们只占用80K字节。因此,对具有长列值的表使用压缩表格格式通常更有效。
对于文件的每个表
的表空间,采用16K压缩页面大小可以降低存储和I / O开销BLOB,
VARCHAR或
TEXT列,因为这些数据往往压缩得很好,因此可能需要更少的溢出页,即使在B树节点他们自己的页面和未压缩的页面一样多。常规表空间不支持16K压缩页面大小(KEY_BLOCK_SIZE)。有关更多信息,请参见
第14.7.9节“InnoDB常规表空间”。
在压缩InnoDB表中,每个压缩页面(无论是1K,2K,4K还是8K)对应于16K字节的未压缩页面(如果innodb_page_size设置为更小的页面
)。要访问页面中的数据,MySQL会从磁盘读取压缩页面(如果该页面不在
缓冲池中),然后将页面解压缩为原始形式。本节介绍如何InnoDB管理相对于压缩表页面的缓冲池。
为了最大限度地减少I / O并减少解压缩页面的需要,缓冲池有时包含压缩和未压缩的数据库页面形式。为了为其他需要的数据库页面腾出空间,MySQL可以 从缓冲池中逐出未压缩页面,同时将压缩页面留在内存中。或者,如果页面在一段时间内未被访问,页面的压缩形式可能会被写入磁盘,以释放其他数据的空间。因此,在任何给定时间,缓冲池可能包含页面的压缩和未压缩形式,或者只包含页面的压缩形式,或者既不包含压缩形式。
MySQL会记录哪些页面保留在内存中,哪些使用最近最少使用(LRU)列表驱逐,以便 热点(频繁访问)的数据倾向于留在内存中。当访问压缩表时,MySQL使用自适应LRU算法在存储器中实现压缩和未压缩页面的适当平衡。这种自适应算法对系统是在I / O绑定还是 CPU绑定中运行很敏感方式。我们的目标是避免在CPU繁忙时花费太多的处理时间来解压缩页面,并且避免在CPU有可用于解压缩压缩页面(可能已存在于内存中)的空闲周期时执行多余的I / O操作。当系统受到I / O限制时,算法更喜欢驱逐一个页面的未压缩副本而不是两个副本,以便为其他磁盘页面留出更多空间成为内存驻留。当系统受到CPU限制时,MySQL更喜欢逐出压缩和未压缩页面,以便可以将更多内存用于“ 热 ”页面,并且不需要仅以压缩形式解压缩内存中的数据。
在将压缩页面写入
数据文件之前,MySQL会将页面的副本写入重做日志(如果从上次写入数据库开始已重新压缩)。这样做是为了确保重做日志可用于
崩溃恢复,即使在不太可能的情况下zlib库升级,并且这种更改引入了压缩数据的兼容性问题。因此,一些日志文件的大小会增加
,或者需要更频繁的
检查点,使用压缩时可以预期。日志文件大小或检查点频率的增加量取决于压缩页面以需要重组和压缩的方式修改的次数。
压缩表需要
梭子鱼文件格式。要在每个表文件表空间中创建压缩表,
innodb_file_per_table必须启用并且innodb_file_format
必须设置为梭子鱼。innodb_file_format在通用表空间中创建压缩表时,不依赖于
设置。有关更多信息,请参见第14.7.9节“InnoDB常规表空间”。在
MySQL企业备份产品支持
的Barracuda文件格式。
传统上,InnoDB
压缩功能主要建议用于只读或以读取为主的
工作负载,例如在
数据仓库
配置中。固态硬盘
存储设备的兴起虽然速度快但相对较小且昂贵,因此压缩对OLTP工作负载也很有吸引力
:高流量的交互式网站可通过使用压缩表来降低其存储需求和每秒I / O操作(IOPS)那些频繁的应用程序
INSERT,
UPDATE和
DELETE操作。
在MySQL 5.6中引入的配置选项使您可以调整压缩对特定MySQL实例的工作方式,重点在于编写密集型操作的性能和可伸缩性:
innodb_compression_level
可以让您调高或缩小压缩程度。较高的值可让您将更多数据放入存储设备,但压缩过程中CPU的开销会增加。当存储空间不重要时,较低的值可以减少CPU开销,或者您期望数据不是特别可压缩的。
innodb_compression_failure_threshold_pct
指定更新压缩表期间压缩失败的截止点
。当这个阈值被传递时,MySQL开始在每个新的压缩页面中留下额外的空闲空间,动态调整空闲空间量直到页面大小百分比
innodb_compression_pad_pct_max
innodb_compression_pad_pct_max
可以调整每个页面中保留的最大空间量,以记录对压缩行的更改,而无需再次压缩整个页面。值越高,可以记录更多的变化而无需重新压缩页面。只有当指定百分比的压缩操作
在运行时“ 失败 ”时,MySQL才会为每个压缩表内的页面使用可变的可用空间量
,这需要昂贵的操作来拆分压缩的页面。
innodb_log_compressed_pages
您可以禁用的写入图像
再压缩
页面到
重做日志。对压缩数据进行更改时可能会发生重新压缩。此选项默认启用,以防止zlib在恢复期间使用不同版本的压缩算法时可能发生的损坏
。如果您确定
zlib版本不会更改,请禁用
innodb_log_compressed_pages
以减少修改压缩数据的工作负载的重做日志生成。
由于使用压缩数据有时需要同时在页面内存中保存压缩版本和未压缩版本,因此,在使用OLTP样式工作负载压缩时,请准备好增加innodb_buffer_pool_size
配置选项的值
。
本节介绍在将表压缩功能与每个表文件的表 空间和常规表空间配合使用时可能遇到的语法警告和错误 。
当innodb_strict_mode被使能(默认值),指定
ROW_FORMAT=COMPRESSED或
KEY_BLOCK_SIZE在CREATE
TABLE或ALTER TABLE
语句如果产生以下错误
innodb_file_per_table被禁用,或者如果
innodb_file_format被设定为
Antelope,而不是
Barracuda。
错误1031(HY000):'t1'的表存储引擎没有这个选项
如果当前配置不允许使用压缩表,则不会创建该表。
innodb_strict_mode禁用时,
如果禁用,则指定ROW_FORMAT=COMPRESSED或
KEY_BLOCK_SIZEin CREATE
TABLE或者ALTER TABLE
语句会生成以下警告
innodb_file_per_table。
MySQL的> SHOW WARNINGS;
+ --------- + ------ + -------------------------------- ------------------------------- +
| 级别| 代码| 留言|
+ --------- + ------ + -------------------------------- ------------------------------- +
| 警告| 1478 | InnoDB:KEY_BLOCK_SIZE需要innodb_file_per_table。|
| 警告| 1478 | InnoDB:忽略KEY_BLOCK_SIZE = 4。|
| 警告| 1478 | InnoDB:ROW_FORMAT = COMPRESSED需要innodb_file_per_table。|
| 警告| 1478 | InnoDB:假设ROW_FORMAT = DYNAMIC。|
+ --------- + ------ + -------------------------------- ------------------------------- +
如果类似的警告发出
innodb_file_format设置为
Antelope,而不是
Barracuda。
这些消息只是警告,而不是错误,并且表格是在没有压缩的情况下创建的,就好像这些选项没有指定一样。
在“ 非严格的 ”行为可让您导入
mysqldump文件到不支持压缩表,即使源数据库包含压缩表的数据库。在这种情况下,MySQL创建表
ROW_FORMAT=COMPACT而不是阻止操作。
要将转储文件导入到新数据库中,并使表格在原始数据库中存在时重新创建,请确保服务器具有适当的配置参数
innodb_file_format和
innodb_file_per_table。
该属性KEY_BLOCK_SIZE仅在ROW_FORMAT被指定为
COMPRESSED或被省略时才被允许。KEY_BLOCK_SIZE使用任何其他
指定会
ROW_FORMAT生成警告,您可以使用该警告进行查看SHOW WARNINGS。但是,表格是非压缩的; 指定的
KEY_BLOCK_SIZE被忽略)。
| 水平 | 码 | 信息 |
|---|---|---|
| 警告 | 1478 | InnoDB: ignoring KEY_BLOCK_SIZE= |
如果在innodb_strict_mode启用时运行
,a KEY_BLOCK_SIZE与ROW_FORMAT其他
任何组合都会
COMPRESSED生成错误,而不是警告,并且不会创建表。
表14.7“ROW_FORMAT和KEY_BLOCK_SIZE选项”
提供了与or
一起使用的概述ROW_FORMAT和
KEY_BLOCK_SIZE选项
。
CREATE TABLEALTER TABLE
表14.7 ROW_FORMAT和KEY_BLOCK_SIZE选项
| 选项 | 使用说明 | 描述 |
|---|---|---|
ROW_FORMAT=REDUNDANT |
在MySQL 5.0.3之前使用的存储格式 | 效率低于ROW_FORMAT=COMPACT; 为了向后兼容 |
ROW_FORMAT=COMPACT |
自MySQL 5.0.3以来的默认存储格式 | 在聚簇索引页中存储长字段值的前缀768字节,其余字节存储在溢出页中 |
ROW_FORMAT=DYNAMIC |
文件每表的表空间需要
innodb_file_format=Barracuda |
如果它们合适,则将值存储在聚集索引页面内; 如果不是,则只存储一个指向溢出页面的20字节指针(无前缀) |
ROW_FORMAT=COMPRESSED |
文件每表的表空间需要
innodb_file_format=Barracuda |
使用zlib压缩表和索引 |
KEY_BLOCK_SIZE= |
文件每表的表空间需要
innodb_file_format=Barracuda |
指定1,2,4,8或16千字节的压缩页面大小; 意味着
ROW_FORMAT=COMPRESSED。对于一般的表空间,不允许有KEY_BLOCK_SIZE等于InnoDB页面大小的值。 |
表14.8“InnoDB严格模式为OFF时的CREATE / ALTER TABLE警告和错误”
汇总了CREATE TABLEor或者
ALTER TABLE语句上的某些配置参数和选项组合出现的错误条件
,以及这些选项如何显示在输出中SHOW TABLE
STATUS。
当innodb_strict_mode是
OFF时,MySQL创建或改变该表中,但如下所示忽略某些设置。您可以在MySQL错误日志中看到警告消息。如果
innodb_strict_mode是
ON,这些指定的选项组合产生的错误,表中没有创建或修改。要查看错误情况的完整描述,请发布以下
SHOW ERRORS语句:例如:
mysql>CREATE TABLE x (id INT PRIMARY KEY, c INT)- >ENGINE=INNODB KEY_BLOCK_SIZE=33333;错误1005(HY000):无法创建表'test.x'(错误号:1478) MySQL的>SHOW ERRORS;+ ------- + ------ + ---------------------------------- --------- + | 级别| 代码| 留言| + ------- + ------ + ---------------------------------- --------- + | 错误| 1478 | InnoDB:无效KEY_BLOCK_SIZE = 33333。| | 错误| 1005 | 无法创建表'test.x'(errno:1478)| + ------- + ------ + ---------------------------------- --------- +
表14.8 InnoDB严格模式关闭时的CREATE / ALTER TABLE警告和错误
| 句法 | 警告或错误情况 | 结果ROW_FORMAT如图所示SHOW TABLE
STATUS |
|---|---|---|
ROW_FORMAT=REDUNDANT |
没有 | REDUNDANT |
ROW_FORMAT=COMPACT |
没有 | COMPACT |
ROW_FORMAT=COMPRESSED或
ROW_FORMAT=DYNAMIC或被
KEY_BLOCK_SIZE指定 |
忽略文件的每个表的表空间,除非双方
并
启用。一般的表空间支持所有行格式(有一些限制),无论
和
设置。请参见14.7.9节,“InnoDB常规表空间”。innodb_file_format=Barracudainnodb_file_per_tableinnodb_file_formatinnodb_file_per_table |
the default row format for file-per-table tablespaces; the
specified row format for general tablespaces |
KEY_BLOCK_SIZE指定了无效(不是1,2,4,8或16) |
KEY_BLOCK_SIZE 被忽略 |
指定的行格式或默认行格式 |
ROW_FORMAT=COMPRESSED并KEY_BLOCK_SIZE指定有效
|
没有; KEY_BLOCK_SIZE指定使用 |
COMPRESSED |
KEY_BLOCK_SIZE与指定的
REDUNDANT,COMPACT
或DYNAMIC行格式 |
KEY_BLOCK_SIZE 被忽略 |
REDUNDANT,COMPACT或者
DYNAMIC |
ROW_FORMAT是没有一个
REDUNDANT,COMPACT,
DYNAMIC或
COMPRESSED |
如果被MySQL解析器识别,则被忽略。否则,会发出错误。 | 默认的行格式或N / A |
当innodb_strict_mode是
ON时,MySQL拒绝无效
ROW_FORMAT或
KEY_BLOCK_SIZE参数问题的错误。当innodb_strict_mode是
OFF时,MySQL发出警告,而不是被忽略的参数无效的错误。
innodb_strict_mode是ON
默认的。
当innodb_strict_mode是
ON时,MySQL拒绝无效
ROW_FORMAT或
KEY_BLOCK_SIZE参数。为了与早期版本的MySQL兼容,默认情况下严格模式未启用; 相反,MySQL会为忽略的无效参数发出警告(而不是错误)。
无法看到所选的
KEY_BLOCK_SIZE使用SHOW TABLE
STATUS。该语句SHOW CREATE
TABLE显示KEY_BLOCK_SIZE
(即使它在创建表时被忽略)。MySQL的真实压缩页面大小不能显示。
如果FILE_BLOCK_SIZE在创建表空间时没有为常规表空间定义,则表空间不能包含压缩表。如果尝试添加压缩表,则会返回错误,如以下示例中所示:
MySQL的>CREATE TABLESPACE `ts1` ADD DATAFILE 'ts1.ibd' Engine=InnoDB;MySQL的>CREATE TABLE t1 (c1 INT PRIMARY KEY) TABLESPACE ts1 ROW_FORMAT=COMPRESSEDKEY_BLOCK_SIZE=8;错误1478(HY000):InnoDB:Tablespace`ts1`不能包含COMPRESSED表
试图向KEY_BLOCK_SIZE常规表空间添加一个无效
的表会返回一个错误,如下例所示:
MySQL的>CREATE TABLESPACE `ts2` ADD DATAFILE 'ts2.ibd' FILE_BLOCK_SIZE = 8192 Engine=InnoDB;MySQL的>CREATE TABLE t2 (c1 INT PRIMARY KEY) TABLESPACE ts2 ROW_FORMAT=COMPRESSEDKEY_BLOCK_SIZE=4;错误1478(HY000):InnoDB:表空间ts2`使用块大小8192,不能 包含一个物理页面大小为4096的表格
对于一般的表空间,
KEY_BLOCK_SIZE表的大小必须等于FILE_BLOCK_SIZE表空间除以1024.例如,如果
FILE_BLOCK_SIZE表空间的大小是8192,KEY_BLOCK_SIZE则表的大小必须是8。
尝试将未压缩的行格式的表添加到配置为存储压缩表的常规表空间中时会返回错误,如以下示例所示:
MySQL的>CREATE TABLESPACE `ts3` ADD DATAFILE 'ts3.ibd' FILE_BLOCK_SIZE = 8192 Engine=InnoDB;MySQL的>CREATE TABLE t3 (c1 INT PRIMARY KEY) TABLESPACE ts3 ROW_FORMAT=COMPACT;错误1478(HY000):InnoDB:表空间ts3`使用块大小8192,不能 包含一个物理页面大小为16384的表格
innodb_strict_mode不适用于一般的表空间。通用表空间的表空间管理规则是独立于,严格执行的
innodb_strict_mode。有关更多信息,请参见第13.1.19节“CREATE TABLESPACE Syntax”。
有关在一般表空间中使用压缩表的更多信息,请参见第14.7.9节“InnoDB常规表空间”。
InnoDB支持驻留在每个表文件表
空间中的表的页面级压缩
。这个功能被称为透明页面压缩。通过COMPRESSION使用CREATE TABLE或
指定属性
来启用页面压缩ALTER TABLE。支持的压缩算法包括Zlib和
LZ4。
页面压缩需要稀疏文件和打孔支持。在Windows上使用NTFS支持页面压缩,以及在内核级别提供打孔支持的MySQL支持的Linux平台的以下子集上:
RHEL 7以及使用内核版本3.10.0-123或更高版本的派生分发版
OEL 5.10(UEK2)内核版本2.6.39或更高版本
OEL 6.5(UEK3)内核版本为3.8.13或更高版本
OEL 7.0内核版本为3.8.13或更高版本
SLE11内核版本3.0-x
SLE12内核版本3.12-x
OES11内核版本3.0-x
Ubuntu 14.0.4 LTS内核版本3.13或更高
Ubuntu 12.0.4 LTS内核版本3.2或更高
Debian 7内核版本3.2或更高
给定Linux发行版的所有可用文件系统可能不支持打孔。
当页面被写入时,它使用指定的压缩算法进行压缩。压缩数据被写入磁盘,打孔机制从页面末尾释放空白块。如果压缩失败,数据将按原样写出。
在Linux系统上,文件系统块大小是用于打孔的单位大小。因此,页面压缩仅适用于页面数据可以压缩到小于或等于
InnoDB页面大小减去文件系统块大小的大小。例如,如果
innodb_page_size=16K文件系统块大小为4K,则页面数据必须压缩到小于或等于12K才能进行打孔。
在Windows系统上,稀疏文件的基础架构基于NTFS压缩。打孔大小是NTFS压缩单位,是NTFS簇大小的16倍。下表中显示了簇大小及其压缩单元:
Windows系统上的页面压缩仅适用于页面数据可以压缩到小于或等于
InnoDB页面大小减去压缩单元大小的大小。
默认的NTFS簇大小为4K,压缩单元大小为64K。这意味着页面压缩对于开箱即用的Windows NTFS配置没有好处,因为最大值
innodb_page_size也是64K。
为了在Windows上工作页面压缩,必须创建文件系统的簇大小小于4K,并且
innodb_page_size必须至少是压缩单元大小的两倍。例如,对于在Windows上工作的页面压缩,您可以创建512字节的群集大小(压缩单元为8KB)的文件系统,并InnoDB使用innodb_page_size16K或更大的
值进行初始化。
要启用页面压缩,请COMPRESSION在CREATE TABLE语句中指定
属性
。例如:
CREATE TABLE t1(c1 INT)COMPRESSION =“zlib”;
您也可以在ALTER TABLE语句中启用页面压缩
。但是,
ALTER TABLE ...
COMPRESSION只更新表空间压缩属性。写入设置新压缩算法后发生的表空间使用新设置,但要将新压缩算法应用于现有页面,必须使用重建表OPTIMIZE TABLE。
ALTER TABLE t1 COMPRESSION =“zlib”; OPTIMIZE TABLE t1;
要禁用页面压缩,请COMPRESSION=None使用
设置
ALTER TABLE。写入设置后COMPRESSION=None不再使用页面压缩的表空间
。要解压缩现有页面,必须OPTIMIZE TABLE在设置之后使用重建表格COMPRESSION=None。
ALTER TABLE t1 COMPRESSION =“None”; OPTIMIZE TABLE t1;
页面压缩元数据位于
INFORMATION_SCHEMA.INNODB_SYS_TABLESPACES
表格中的以下列中:
FS_BLOCK_SIZE:文件系统块大小,即用于打孔的单位大小。
FILE_SIZE:文件的表观大小,表示文件的最大大小,未压缩。
ALLOCATED_SIZE:文件的实际大小,即磁盘上分配的空间量。
在类Unix系统上,以字节为单位显示明显的文件大小(相当于
)。要查看磁盘上分配的实际空间量(等同于
),请使用。该
选项以字节而不是块打印分配的空间,以便将其与输出进行比较
。
ls -l
tablespace_name.ibdFILE_SIZEALLOCATED_SIZEdu
--block-size=1
tablespace_name.ibd--block-size=1ls -l
使用SHOW CREATE TABLE查看当前页面压缩设置(Zlib,
Lz4,或None)。表格可能包含具有不同压缩设置的页面混合。
在以下示例中,从表中检索employees表的页面压缩元数据
INFORMATION_SCHEMA.INNODB_SYS_TABLESPACES
。
#使用Zlib页面压缩功能创建员工表
CREATE TABLE employees(
emp_no INT NOT NULL,
birth_date DATE NOT NULL,
first_name VARCHAR(14)NOT NULL,
last_name VARCHAR(16)NOT NULL,
性别ENUM('M','F')NOT NULL,
hire_date DATE NOT NULL,
PRIMARY KEY(emp_no)
)COMPRESSION =“zlib”;
#插入数据(未显示)
#在INFORMATION_SCHEMA.INNODB_SYS_TABLESPACES中查询页面压缩元数据
MySQL的> SELECT SPACE, NAME, FS_BLOCK_SIZE, FILE_SIZE, ALLOCATED_SIZE FROM
INFORMATION_SCHEMA.INNODB_SYS_TABLESPACES WHERE NAME='employees/employees'\G
*************************** 1. row ******************** *******
空间:45
名称:员工/员工
FS_BLOCK_SIZE:4096
FILE_SIZE:23068672
ALLOCATED_SIZE:19415040
员工表的页面压缩元数据显示明显的文件大小为23068672字节,而实际文件大小(使用页面压缩)为19415040字节。文件系统块大小为4096字节,这是用于打孔的块大小。
如果文件系统块大小(或Windows上的压缩单元大小)* 2>,则禁用页面压缩
innodb_page_size。
页面压缩不支持驻留在共享表空间中的表,其中包括系统表空间,临时表空间和常规表空间。
撤消日志表空间不支持页面压缩。
重做日志页面不支持页面压缩。
用于空间索引的R树页面不被压缩。
属于压缩表(ROW_FORMAT=COMPRESSED)的页面保持原样。
恢复期间,更新的页面以未压缩的形式写出。
在不支持所使用的压缩算法的服务器上加载页面压缩的表空间会导致I / O错误。
在降级到不支持页面压缩的早期版本的MySQL之前,解压缩使用页面压缩功能的表。要解压缩一个表,运行
ALTER TABLE ...
COMPRESSION=None和OPTIMIZE
TABLE。
如果所使用的压缩算法在两台服务器上均可用,则可以在Linux和Windows服务器之间复制页面压缩的表空间。
将页面压缩的表空间文件从一台主机移动到另一台主机时,保留页面压缩需要一个保存稀疏文件的实用程序。
在NVMFS的Fusion-io硬件上比在其他平台上可以实现更好的页面压缩,因为NVMFS旨在利用打孔功能。
使用具有较大InnoDB页面大小和较小文件系统块大小的页面压缩功能
可能导致写入放大。例如,InnoDB具有4KB文件系统块大小的64KB 的最大页面大小可以改善压缩,但是也可能增加对缓冲池的需求,导致增加的I / O和潜在的写入放大。
随着InnoDB发展,与以前版本不兼容的数据文件格式InnoDB有时需要支持新功能。为了帮助管理升级和降级情况下的兼容性以及运行不同版本MySQL的系统,InnoDB使用命名文件格式。InnoDB目前支持两种命名的文件格式,Antelope
和Barracuda。
羚羊是原来的
InnoDB文件格式,以前没有名称。它支持表格的
COMPACT和
REDUNDANT行格式InnoDB。
梭子鱼是最新的文件格式。它支持所有InnoDB行格式,包括较新的
COMPRESSED和
DYNAMIC行格式。与COMPRESSED和
DYNAMIC行格式相关的功能
包括压缩表,高效存储页外列和索引键前缀高达3072字节(innodb_large_prefix)。请参见
第14.11节“InnoDB行存储和行格式”。
本节讨论InnoDB为新InnoDB表启用文件格式,验证MySQL版本之间不同文件格式的兼容性,以及识别正在使用的文件格式。
InnoDB文件格式设置不适用于存储在 一般表空间中的表。常规表空间提供对所有行格式和相关功能的支持。有关更多信息,请参见 第14.7.9节“InnoDB常规表空间”。
以下文件格式配置参数具有新的默认值:
将innodb_file_format
默认值更改为Barracuda。之前的默认值是Antelope。
将innodb_large_prefix
默认值更改为ON。之前的默认值是OFF。
以下文件格式配置参数已弃用,并可能在未来版本中删除:
提供的文件格式配置参数用于创建与InnoDBMySQL 5.1 早期版本兼容的表
。现在MySQL 5.1已经到了产品生命周期的最后阶段,这些参数不再需要了。
该innodb_file_format
配置选项使InnoDB文件格式
文件的每个表的
表空间。
Barracuda是默认
innodb_file_format设置。在早期版本中,默认文件格式为
Antelope。
该innodb_file_format
配置选项已被弃用,并可能在将来的版本中删除。有关更多信息,请参见
第14.10节“InnoDB文件格式管理”。
您可以innodb_file_format在启动mysqld时或在选项文件中(my.cnf在Unix上,
my.ini在Windows上)设置命令行中的值
。您还可以使用SET GLOBAL语句动态更改它。
SET GLOBAL innodb_file_format =梭鱼;
InnoDB文件格式设置不适用于存储在一般表空间中的表格。常规表空间提供对所有行格式和相关功能的支持。有关更多信息,请参见第14.7.9节“InnoDB常规表空间”。
innodb_file_format
使用TABLESPACE
[=] innodb_system表格选项
CREATE TABLE或
在系统表空间中ALTER TABLE存储
DYNAMIC表格时,
该设置不适用。
innodb_file_format
创建使用DYNAMIC行格式的表时,
该设置将被忽略
。有关更多信息,请参见第14.11.3节“动态和压缩行格式”。
InnoDB集成了多项检查功能,以防止在InnoDB数据文件上使用较新的文件格式运行旧版MySQL服务器时可能发生的崩溃和数据损坏。这些检查在服务器启动时以及第一次访问表时进行。本节介绍这些检查,如何控制它们,以及可能出现的错误和警告条件。
当使用InnoDB的最新版本(InnoDB的MySQL 5.5及更高版本)以及旧版本(MySQL 5.1或更早版本,内置InnoDB而不是InnoDB插件)时,您只需考虑向后文件格式的兼容性。为了最大限度地减少兼容性问题的机会,您可以在InnoDB插件上标准化所有MySQL 5.1和更早版本的数据库服务器。
一般来说,较新版本的InnoDB可能会创建一个表或索引,无法安全地使用InnoDB的旧版本进行读取或写入,而没有崩溃,挂起,错误结果或损坏的风险。InnoDB包含防范这些情况的机制,并帮助保持数据库文件和InnoDB版本之间的兼容性。通过这种机制,您可以利用InnoDB版本的一些新功能(例如性能改进和错误修复),并保留将数据库与旧版InnoDB一起使用的选项,防止意外使用创建向下的新功能不兼容的磁盘文件。
如果一个版本的InnoDB支持特定的文件格式(无论该格式是否为默认格式),则可以查询和更新任何需要该格式或更早格式的表格。基于启用的特定文件格式,仅限使用新功能创建新表的限制。相反,如果表空间包含使用不受支持的文件格式的表或索引,则即使对于读取访问,也不能访问它。
将InnoDB表空间“ 降级 ”为早期的Antelope文件格式的唯一方法是将数据复制到使用较早格式的表空间中的新表中。
确定现有InnoDB表空间文件格式的最简单方法是使用该SHOW TABLE STATUS命令或查询表来检查其包含的表的属性INFORMATION_SCHEMA.TABLES。如果该
Row_format表的报告为
'Compressed'或'Dynamic',则包含该表的表空间支持梭子鱼格式。
每个InnoDB文件 - 每表表空间(由*.ibd文件表示
)文件都标有文件格式标识符。系统表空间(由ibdata文件表示
)被标记为一组InnoDB数据库文件中使用的
“ 最高 ”文件格式,并且在打开文件时检查该标记。
使用Barracuda文件格式的标识符
创建压缩表或带有表的表
ROW_FORMAT=DYNAMIC,可以更新相应的每个.ibd文件表文件的文件头和InnoDB数据字典中的表类型。从那时起,该表不能用于不支持Barracuda文件格式的InnoDB版本。为防止异常行为,InnoDB在表打开时执行兼容性检查。(在许多情况下,ALTER TABLE
语句重新创建一个表并因此改变它的属性。在第14.13.1节“在线DDL概述”中描述了添加或删除索引而不重建表的特殊情况
。)
一般的表空间也由*.ibd文件表示
,支持羚羊和梭子鱼文件格式。有关常规表空间的更多信息,请参见
第14.7.9节“InnoDB常规表空间”。
为了避免混淆,为了讨论的目的,我们将术语“ ib-file set ”定义为InnoDB作为一个单元管理的一组操作系统文件。ib文件集包括以下文件:
ibdata
包含内部系统信息(包括内部目录和撤消信息)并可能包含用户数据和索引
的系统表空间(一个或多个文件)。
零个或多个单表表空间(也称为“ 每个表文件”文件,命名*.ibd
文件)。
InnoDB日志文件; 通常是两个,ib_logfile0
而且ib_logfile1。用于崩溃恢复和备份。
一个“ IB-文件集 ”不包括相应的
.frm包含约InnoDB表的元数据文件。这些.frm文件由MySQL创建和管理,有时可能与InnoDB中的内部元数据不同步。
即使来自多个数据库的多个表也可以存储在一个“ ib文件集 ”中。(在MySQL中, “ 数据库 ”是表的逻辑集合,其他系统称为“ 模式 ”或 “ 目录 ”。)
为了防止InnoDB打开ib文件集时可能发生的崩溃或数据损坏,它会检查它是否完全支持ib文件集内使用的文件格式。如果系统在崩溃或“ 快速关闭 ”
(即innodb_fast_shutdown大于零)之后重新启动,则可能有磁盘上的数据结构(例如重做或撤销条目或双重写入页面)也处于
“ 太新 “格式为当前软件。在恢复过程中,如果访问这些数据结构,可以对数据文件造成严重损坏。文件格式的启动检查在任何恢复过程开始之前发生,从而防止新表的一致性问题或MySQL服务器的启动问题。
从版本InnoDB 1.0.1开始,系统表空间会记录任何属于ib文件集的表空间中的任何表所使用的“ 最高 ”文件格式的标识符或标记。针对这种文件格式标签检查由配置参数来控制
innodb_file_format_check,这是ON通过默认。
如果系统表空间中的文件格式标记比当前正在执行的特定软件支持的最高版本更新或更高,并且如果
innodb_file_format_check是
ON,则在服务器启动时发出以下错误:
InnoDB:错误:系统表空间位于 该版本不支持的文件格式
您也可以设置
innodb_file_format为文件格式名称。如果当前软件不支持指定的文件格式,则会阻止InnoDB启动。它还将“ 高水位 ”设置为您指定的值。innodb_file_format_check如果您手动“ 降级 ” ib文件集中的所有表,设置的能力
是有用的(对未来的版本)
。然后,如果您随后使用InnoDB的较早版本访问ib文件集,则可以在启动时依赖文件格式检查。
在某些有限的情况下,您可能需要启动服务器并使用ib文件集,该文件集采用新文件格式,而您所使用的软件不支持该文件格式。如果您将配置参数设置
innodb_file_format_check为
OFF,InnoDB将打开数据库,但在错误日志中发出以下警告消息:
InnoDB:警告:系统表空间位于 该版本不支持的文件格式
这是一个危险的设置,因为它允许恢复过程运行,如果以前的关闭是崩溃或“ 快速关闭 ”,可能会损坏数据库。如果您确定先前的关闭已完成
,则只应设置
innodb_file_format_check为
,以便基本上不会发生恢复过程。
OFFinnodb_fast_shutdown=0
该参数
innodb_file_format_check
仅影响打开数据库时发生的情况,而不是随后发生。相反,参数
innodb_file_format(启用特定格式)仅确定是否可以使用启用的格式创建新表,并且不影响数据库是否可以打开。
文件格式标记是一个“ 高水位标记 ”,因此在服务器启动之后,如果创建“ 高 ”格式的表或者读取或写入现有表(假设其格式为支持的)。如果以比运行软件支持的格式更高的格式访问现有表,则不会更新系统表空间标记,但将应用表级别兼容性检查(并发出错误),如
第14.10.2.2节“打开表格时的兼容性检查“。任何时候更新高水位标记的值
innodb_file_format_check也会更新,因此该命令将SELECT
@@innodb_file_format_check;显示当前已打开的ib文件集中已知由表使用且当前正在执行的软件支持的最新文件格式的名称。
当首次访问表时,InnoDB(包括InnoDB 1.0之前的一些版本)将检查表中存储的表空间的文件格式是否完全受支持。此检查可防止遇到使用“ 太新 ”数据结构的表时发生的崩溃或损坏。
所有使用发行版支持的任何文件格式的表都可以读取或写入(假设用户具有足够的权限)。innodb_file_format即使给定版本支持文件格式,系统配置参数的设置
也可以防止创建使用特定文件格式的新表。这样的设置可能用于保持向后兼容性,但它不会阻止访问任何使用支持格式的表。
如果在创建表时使用了新的文件格式,那么早于5.0.21的MySQL版本不能可靠地使用由较新版本创建的数据库文件。为了防止各种错误情况或损坏,InnoDB在打开文件时(例如首次访问表格时)检查文件格式兼容性。如果当前运行的InnoDB版本不支持InnoDB数据字典中表类型标识的文件格式,则MySQL报告以下错误:
错误1146(42S02):表'test。t1'不存在
InnoDB还会向错误日志写入消息:
InnoDB:表test/t1:未知表类型33
表类型应该等于表空间标志,它包含第14.10.3节“识别正在使用的文件格式”中讨论的文件格式版本 。
MySQL 4.1之前的InnoDB版本不包括数据库文件中的表格格式标识符,并且MySQL 5.0.21之前的版本未包含表格格式兼容性检查。因此,如果在5.0.21之前的InnoDB版本中使用新文件格式的表格,则无法确保正确的操作。
InnoDB 1.0和更高版本(表空间标记和运行时检查)中的文件格式管理功能允许InnoDB尽快验证软件的运行版本是否可以正确处理数据库中存在的表。
如果允许InnoDB打开一个包含不支持的格式的数据库(通过设置参数
innodb_file_format_check为
OFF),本节中描述的表级检查仍然适用。
强烈建议 用户不要使用包含Barracuda文件格式表的数据库文件,而InnoDB版本比InnoDB插件早于MySQL 5.1。可能重建这些表格以使用Antelope格式。
如果使用
配置选项启用不同的文件格式innodb_file_format,则更改仅适用于新创建的表格。另外,当您创建新表时,包含该表的表空间将标记为支持表的功能所需的“ 最早 ”或
“ 最简单 ”的文件格式。例如,如果启用
Barracuda文件格式并创建不使用动态或压缩行格式的新表,则包含该表的新表空间将标记为使用
Antelope文件格式。
识别给定表格使用的文件格式很容易。Antelope如果报告的行格式SHOW TABLE STATUS为Compact或,则
表格使用文件格式Redundant。Barracuda如果报告的行格式SHOW TABLE STATUS为Compressed或,则
表格使用文件格式Dynamic。
MySQL的> SHOW TABLE STATUS\G
*************************** 1. row ******************** *******
名称:t1
引擎:InnoDB
版本:10
Row_format:紧凑
行数:0
Avg_row_length:0
Data_length:16384
Max_data_length:0
Index_length:16384
Data_free:0
Auto_increment:1
Create_time:2014-11-03 13:32:10
Update_time:NULL
Check_time:NULL
整理:latin1_swedish_ci
校验和:NULL
Create_options:
评论:
您还可以使用InnoDB
INFORMATION_SCHEMA表格识别给定表格或表格空间使用的文件格式。例如:
MySQL的>SELECT * FROM INFORMATION_SCHEMA.INNODB_SYS_TABLES WHERE NAME='test/t1'\G*************************** 1. row ******************** ******* TABLE_ID:44 NAME:test / t1 FLAG:1 N_COLS:6 空间:30 FILE_FORMAT:羚羊 ROW_FORMAT:紧凑 ZIP_PAGE_SIZE:0 MySQL的>SELECT * FROM INFORMATION_SCHEMA.INNODB_SYS_TABLESPACES WHERE NAME='test/t1'\G*************************** 1. row ******************** ******* 空间:30 NAME:test / t1 FLAG:0 FILE_FORMAT:羚羊 ROW_FORMAT:紧凑或冗余 PAGE_SIZE:16384 ZIP_PAGE_SIZE:0
每个InnoDB表空间文件(名称匹配
*.ibd)都使用用于创建表和索引的文件格式进行标记。修改文件格式的方法是重新创建表及其索引。重新创建表及其索引的最简单方法是在每个要修改的表上使用以下命令:
ALTER TABLEtROW_FORMAT =format_name;
如果您将文件格式修改为降级为较旧的MySQL版本,则表格存储格式中可能存在不兼容的情况,需要执行其他步骤。有关降级到以前的MySQL版本的信息,请参见 第2.11.2节“降级MySQL”。
本节讨论InnoDB功能如表
压缩,长变长列值的离页存储和大索引键前缀(innodb_large_prefix)是如何由InnoDB表格的行格式控制的。它还讨论了选择正确行格式的注意事项,以及MySQL版本之间行格式的兼容性。
行和相关列的存储会影响查询和DML操作的性能。当更多的行适合单个磁盘页面时,查询和索引查找可以更快地工作,InnoDB缓冲池中所需的缓存内存更少,并且需要更少的I / O来为数字和短字符串列写出更新的值。
每个InnoDB表中的数据分为多 页。构成每个表的页面被排列在称为B树索引的树数据结构中 。表格数据和 二级索引都使用这种类型的结构。表示整个表的B树索引称为 聚集索引,根据主键列组织 索引。索引数据结构的节点包含该行(对于聚集索引)或索引列和主键列(对于二级索引)中的所有列的值。
可变长度列是此规则的一个例外。诸如BLOB和VARCHAR
太长而不适合B树页面的列被存储在被称为溢出页面的单独分配的磁盘
页面上。我们将这些列称为离页列。这些列的值存储在单个链接的溢出页面列表中,每个这样的列都有自己的一个或多个溢出页面的列表。在某些情况下,长列值的所有或前缀都存储在B-树中,以避免浪费存储空间并消除读取单独页面的需要。
以下各节介绍如何配置InnoDB表格的行格式
以控制如何存储可变长度列值。行格式配置还确定表压缩功能和大型索引键前缀功能(innodb_large_prefix)的可用性
。
默认行格式由innodb_default_row_format默认值定义
DYNAMIC。当ROW_FORMAT表格选项未明确定义或
ROW_FORMAT=DEFAULT指定时,将使用默认行格式。
表格的行格式可以使用ROW_FORMATa CREATE TABLE或
ALTER TABLE语句中的表格选项
明确定义
。例如:
CREATE TABLE t1(c1 INT)ROW_FORMAT = DYNAMIC;
明确定义的ROW_FORMAT设置将覆盖隐式默认值。指定
ROW_FORMAT=DEFAULT等同于使用隐式默认值。
该innodb_default_row_format
选项可以动态设置:
MySQL的> SET GLOBAL innodb_default_row_format=DYNAMIC;
有效的innodb_default_row_format
选项包括DYNAMIC,
COMPACT,和REDUNDANT。COMPRESSED不支持在系统表空间中使用的
行格式不能被定义为默认值。它只能在a CREATE TABLE或
ALTER TABLE语句中明确指定
。试图设置innodb_default_row_format
为COMPRESSED返回错误:
MySQL的> SET GLOBAL innodb_default_row_format=COMPRESSED;
错误1231(42000):变量'innodb_default_row_format'
不能设置为'COMPRESSED'的值
新创建的表格使用在未明确指定选项或使用选项innodb_default_row_format时
定义的行格式
。例如,以下
语句使用由定义的行格式
。
ROW_FORMATROW_FORMAT=DEFAULTCREATE TABLEinnodb_default_row_format
CREATE TABLE t1(c1 INT);
CREATE TABLE t2(c1 INT)ROW_FORMAT = DEFAULT;
如果ROW_FORMAT未明确指定选项或者何时ROW_FORMAT=DEFAULT使用选项,则重建表的任何操作也会静默地将表格的行格式更改为由其定义的格式
innodb_default_row_format。
表重建操作包括ALTER
TABLE使用
操作ALGORITHM=COPY或ALTER
TABLE使用ALGORITHM=INPLACE需要重建表的操作
。有关DDL操作的联机状态的概述,请参阅表14.10,“DDL操作的联机状态”。
OPTIMIZE TABLE也是一个桌子重建操作。
以下示例演示了一个表重建操作,它默默更改未创建明确定义的行格式而创建的表格的行格式。
MySQL的>SELECT @@innodb_default_row_format;+ ----------------------------- + | @@ innodb_default_row_format | + ----------------------------- + | 动态| + ----------------------------- + MySQL的>CREATE TABLE t1 (c1 INT);MySQL的>SELECT * FROM INFORMATION_SCHEMA.INNODB_SYS_TABLES WHERE NAME LIKE 'test/t1' \G*************************** 1. row ******************** ******* TABLE_ID:54 NAME:test / t1 国旗:33 N_COLS:4 空间:35 FILE_FORMAT:梭子鱼 ROW_FORMAT:动态 ZIP_PAGE_SIZE:0 SPACE_TYPE:单一 MySQL的>SET GLOBAL innodb_default_row_format=COMPACT;MySQL的>ALTER TABLE t1 ADD COLUMN (c2 INT);MySQL的>SELECT * FROM INFORMATION_SCHEMA.INNODB_SYS_TABLES WHERE NAME LIKE 'test/t1' \G*************************** 1. row ******************** ******* TABLE_ID:55 NAME:test / t1 FLAG:1 N_COLS:5 空间:36 FILE_FORMAT:羚羊 ROW_FORMAT:紧凑 ZIP_PAGE_SIZE:0 SPACE_TYPE:单一
从改变现有表的行格式之前,请考虑以下潜在的问题REDUNDANT或
COMPACT对DYNAMIC。
的REDUNDANT和
COMPACT行格式支持的767个字节的最大索引关键字前缀长度而
DYNAMIC和COMPRESSED
如果行格式支持的3072个字节的索引关键字前缀长度innodb_large_prefix
配置选项被启用。在复制环境中,如果innodb_default_row_format
设置为DYNAMIC在主站和设置
COMPACT在从服务器上,下面的DDL语句,它没有明确定义行格式,成功在主,但未能对从站:
CREATE TABLE t1(c1 INT PRIMARY KEY,c2 VARCHAR(5000),KEY i1(c2(3070)));
有关相关信息,请参见 第14.8.1.7节“InnoDB表限制”。
如果innodb_default_row_format
源服务器上的设置与目标服务器上的设置不同,则导入未明确定义行格式的表会导致模式不匹配错误
。有关更多信息,请参阅第14.7.6节“将文件 - 每个表格表空间复制到另一个实例”中概述的限制。
要查看表格的行格式,请发出
SHOW TABLE STATUS语句或查询INFORMATION_SCHEMA.TABLES。
SELECT * FROM INFORMATION_SCHEMA.INNODB_SYS_TABLES WHERE NAME LIKE'test / t1'\ G
InnoDB表格
的行格式决定了其物理行结构。有关更多信息,请参见
第14.8.1.2节“InnoDB表的物理行结构”。
当使用ROW_FORMAT=DYNAMIC
or 创建表时ROW_FORMAT=COMPRESSED,
InnoDB可以将完全离页的长可变长度列值(for VARCHAR,
VARBINARYand
BLOB和
TEXTtype)存储在聚合索引记录中,其中聚集索引记录仅包含指向溢出页面的20字节指针。InnoDB还将长度大于或等于768字节的固定长度字段编码为可变长度字段。例如,
CHAR(255)如果字符集的最大字节长度大于3,则列可能会超过768个字节utf8mb4。
是否有任何列存储在页外,取决于页面大小和行的总大小。当行太长时,
InnoDB选择离页存储的最长列,直到聚簇索引记录适合
B树页面。
TEXT并且
BLOB小于或等于40个字节的列总是在线存储。
该DYNAMIC行格式保持存储在它是否适合的索引节点整个行的效率(如做的
COMPACT和REDUNDANT
格式),但是DYNAMIC行格式避免填充B-树节点具有大量长列的数据字节的问题。该DYNAMIC格式基于这样的想法,即如果长数据值的一部分存储在页外,通常最有效的方法是将所有的值存储在页外。使用DYNAMIC格式,较短的列可能会保留在B-tree节点中,从而最大限度地减少任何给定行所需的溢出页数。
该COMPRESSED行格式使用类似的内部细节关闭页存储为DYNAMIC行格式,从表和索引数据的附加存储和性能的考虑被压缩,并使用较小的页大小。使用COMPRESSED行格式,该
KEY_BLOCK_SIZE选项控制聚集索引中存储了多少列数据,以及溢出页面上放置了多少数据。有关COMPRESSED行格式的完整详细信息
,请参见
第14.9节“InnoDB表和页面压缩”。
Both DYNAMIC and COMPRESSED
row formats support index key prefixes up to 3072 bytes. This
feature is controlled by the
innodb_large_prefix configuration
option, which is enabled by default. See the
innodb_large_prefix option
description for more information.
使用COMPRESSED行格式的表格可以在每个文件表格空间或一般表格
空间中
创建。系统表空间不支持
COMPRESSED行格式。要将COMPRESSED表存储
在每个文件表的表空间中,innodb_file_per_table
必须启用并且
innodb_file_format必须设置为
Barracuda。在
innodb_file_per_table和
innodb_file_format配置选项并不适用于一般的表空间。一般的表空间支持所有的行格式,但需要注意的是,由于物理页面大小不同,压缩和未压缩的表不能共存于相同的常规表空间中。有关常规表空间的更多信息,请参阅
第14.7.9节“InnoDB常规表空间”。
DYNAMIC表可以存储在每个表的文件表空间,常规表空间和系统表空间中。要将DYNAMIC表存储在系统表空间中,必须使用TABLESPACE [=] innodb_system
带有CREATE TABLE或
的表选项ALTER TABLE。在
innodb_file_per_table和
innodb_file_format配置选项并不适用于一般的表空间,也没有使用时,它们是适用TABLESPACE [=]
innodb_system表选项存储
DYNAMIC在系统表空间表。
您可以DYNAMIC通过禁用innodb_file_per_table和使用常规CREATE TABLE或ALTER
TABLE语句将表添加到系统表空间
。该
innodb_file_format设置被忽略。一个DYNAMIC表始终使用
Barracuda的文件格式。
DYNAMIC和COMPRESSED行格式是变化COMPACT排格式,因此处理CHAR
存储在相同的方式COMPACT行格式。有关更多信息,请参见
第14.8.1.2节“InnoDB表的物理行结构”。
为数据库文件InnoDB使用未命名文件格式(现称为Antelope)的
早期版本。用这种文件格式,表格用ROW_FORMAT=COMPACT或
定义
ROW_FORMAT=REDUNDANT。使用这些行格式,
可以在B-tree节点内的索引记录中InnoDB存储最多768个字节的可变长度列(VARCHAR,,
VARBINARY和
BLOB和
TEXT类型),其余部分存储在溢出页面中。
还将长度大于或等于768字节的固定长度字段编码为可变长度字段,这些字段可以存储在页外。例如,a
InnoDBCHAR(255)如果字符集的最大字节长度大于3,则字段可能会超过768个字节utf8mb4。
使用Antelope文件格式时,如果列的值为768字节或更少,则不需要溢出页面,并且可能会导致I / O节省一些,因为该值位于B树节点中。这适用于相对较短的BLOBs,但可能导致B树节点填充数据而不是关键值,从而降低其效率。具有许多BLOB列的表可能会导致B-tree节点变得数据太满,并且包含的行太少,这使得整个索引效率低于行较短或列值存储在页外。
有关使用REDUNDANT或COMPACT
行格式的表的物理行结构的信息,请参见第14.8.1.2节“InnoDB表的物理行结构”。
作为DBA,您必须管理磁盘I / O以防止I / O子系统变得饱和,并管理磁盘空间以避免填满存储设备。该ACID设计模型需要一定量的I / O可能似乎是多余的,但有助于确保数据的可靠性。在这些约束条件下,
InnoDB尝试优化数据库工作和磁盘文件的组织以最小化磁盘I / O的数量。有时候,I / O被推迟到数据库不忙,或者直到所有的事情都需要进入一致的状态,比如在快速关闭后的数据库重启过程中。
本节讨论使用默认类型的MySQL表(也称为InnoDB表)来处理I / O和磁盘空间的主要注意事项
:
控制用于提高查询性能的后台I / O数量。
启用或禁用以额外I / O为代价提供额外耐用性的功能。
将表组织成许多小文件,几个大文件或两者的组合。
将重做日志文件的大小与日志文件变满时发生的I / O活动进行平衡。
如何重新组织表以获得最佳查询性能。
InnoDB尽可能使用异步磁盘I / O,通过创建大量线程来处理I / O操作,同时在I / O仍在进行时允许其他数据库操作继续。在Linux和Windows平台上,InnoDB使用可用的操作系统和库函数来执行“ 本地 ”异步I / O。在其他平台上,InnoDB仍然使用I / O线程,但这些线程可能实际上等待I / O请求完成; 这种技术被称为“ 模拟 ”
异步I / O。
如果InnoDB可以确定很快就会需要数据的可能性很高,则它会执行预读操作以将该数据带入缓冲池,以使其在内存中可用。对连续数据做出一些较大的读取请求可能比创建几个小的扩展请求更有效。有两个预读启发式InnoDB:
在顺序预读中,如果InnoDB
通知表空间中的段的访问模式是连续的,则它预先向I / O系统发送一批数据库页的读取。
在随机预读中,如果InnoDB通知表空间中的某个区域似乎处于完全读入缓冲池的过程中,则会将剩余的读数发布到I / O系统。
有关配置预读试探法的信息,请参见 第14.6.3.5节“配置InnoDB缓冲池预取(预读)”。
InnoDB使用一种新颖的文件刷新技术,涉及称为双写缓冲区的结构
,在大多数情况下(innodb_doublewrite=ON),默认启用。它增加了崩溃或停电后恢复的安全性,并通过减少fsync()操作需求来提高大多数Unix系统的性能。
在将页面InnoDB
写入数据文件之前,首先将它们写入连续的表空间区域,称为doublewrite缓冲区。只有在写入和刷新到双InnoDB
写缓冲区之后,才会将页面写入数据文件中的正确位置。如果操作系统,存储子系统或
mysqld进程在页面写入过程中崩溃(导致页面被破坏
),InnoDB稍后可以在恢复过程中从双写缓冲区中找到页面的正确副本。
如果系统表空间文件(“ ibdata文件 ”)位于支持原子写入的Fusion-io设备上,则会自动禁用双写缓冲,并将Fusion-io原子写入用于所有数据文件。由于双写缓冲区设置是全局性的,所以对于驻留在非Fusion-io硬件上的数据文件,也会禁用双写缓冲。此功能仅在Fusion-io硬件上受支持,并且仅适用于Linux上的Fusion-io NVMFS。要充分利用此功能,建议使用此
innodb_flush_method设置
O_DIRECT。
您在配置文件中使用innodb_data_file_path
配置选项在InnoDB
系统表空间中定义的数据文件
。这些文件被逻辑连接起来以形成系统表空间。没有使用条纹。您无法定义您的表分配到系统表空间的哪个位置。在新创建的系统表空间中,InnoDB从第一个数据文件开始分配空间。
为避免在系统表空间中存储所有表和索引时出现的问题,可以启用
innodb_file_per_table
配置选项(默认值),该选项将每个新创建的表存储在单独的表空间文件(带扩展名
.ibd)中。对于以这种方式存储的表,磁盘文件中的碎片较少,并且在截断表时,该空间将返回到操作系统,而不是仍然由InnoDB在系统表空间中保留。有关更多信息,请参见
第14.7.4节“InnoDB文件 - 每个表空间”。
您也可以将表存储在
一般的表空间中。常规表空间是使用CREATE TABLESPACE
语法创建的共享表空间。它们可以在MySQL数据目录之外创建,能够保存多个表格,并支持所有行格式的表格。有关更多信息,请参见
第14.7.9节“InnoDB常规表空间”。
每个表空间由数据库页面组成
。MySQL实例中的每个表空间都具有相同的页面大小。默认情况下,所有表空间的页面大小为16KB; 通过innodb_page_size在创建MySQL实例时指定选项,可以将页面大小减小到8KB或4KB
。您还可以将页面大小增加到32KB或64KB。有关更多信息,请参阅
innodb_page_size文档。
页被分成
区段大小为1MB用于尺寸的页面到16KB(64次连续的16KB的页面,或128 8KB页或256 4KB页)。对于32KB的页面大小,区段大小为2MB。对于64KB的页面大小,区段大小为4MB。在
“ 文件 ”表空间内被称为
段在
InnoDB。(这些段与回滚段不同
,后者实际上包含许多表空间段。)
当一个分段在表空间内增长时,一次
InnoDB为其分配前32个页面。之后,InnoDB开始为该细分受众群分配整个范围。InnoDB
可以一次将最多4个区段添加到大型区段,以确保数据的良好顺序性。
两个分段分配给每个索引
InnoDB。一个用于
B树的非叶节点,另一个用于叶节点。在磁盘上保持叶节点连续可以实现更好的顺序I / O操作,因为这些叶节点包含实际的表数据。
表空间中的某些页面包含其他页面的位图,因此InnoDB表空间中的一些扩展区不能作为整体分配给段,而只能作为单独页面分配。
当您通过发出SHOW TABLE STATUS语句要求表空间中的可用空间时,请
InnoDB报告表空间中的空闲空间。InnoDB总是保留一些清理和其他内部目的的程度; 这些保留的扩展区不包含在可用空间中。
从表中删除数据时,InnoDB
合同对应的B树索引。释放空间是否可用于其他用户取决于删除模式是否将个别页面或扩展区释放到表空间。删除表或删除其中的所有行可确保将空间释放给其他用户,但请记住,删除的行仅通过清除操作进行物理删除,删除
操作在事务回滚或一致读取不再需要它们一段时间后自动发生。(请参见
第14.3节“InnoDB多版本控制”。)
对于4KB,8KB,16KB和32KB innodb_page_size设置,最大行长度略小于数据库页面的一半
。例如,对于默认的16KB InnoDB页面大小,最大行长度略小于8KB 。对于64KB的页面,最大行长度略小于16KB。
如果一行没有超过最大行长度,则它全部存储在本地页面中。如果一行超过最大行长度,则将可变长度列选择用于外部页外存储,直到该行适合最大行长度限制。可变长度列的外部页外存储按行格式不同:
精简和冗余行格式
当为外部页外存储选择可变长度的列时,InnoDB将本地前768个字节存储在该行中,其余部分存储在溢出页面中。每个这样的列都有自己的溢出页面列表。768字节的前缀伴随着一个20字节的值,该值存储列的真实长度并指向溢出列表,其中存储剩余的值。请参见
第14.11.4节“精简和冗余行格式”。
DYNAMIC和COMPRESSED行格式
当为外部页外存储选择可变长度列时,InnoDB将20字节指针本地存储在行中,其余部分存储在溢出页中。请参见第14.11.3节“动态和压缩行格式”。
使你的日志文件非常大时可以减少磁盘I / O的 检查点。将日志文件的总大小设置为与缓冲池一样大或者甚至更大是很有意义的。尽管在过去,大型日志文件可能会让崩溃恢复花费过多时间,从MySQL 5.5开始,崩溃恢复的性能增强使得可以在崩溃后快速启动时使用大型日志文件。(严格地说,这个性能改进适用于InnoDB Plugin 1.0.7及更高版本的MySQL 5.1,MySQL 5.5中这种改进在默认InnoDB存储引擎中可用。)
InnoDB实现称为模糊检查点的
检查点机制。小批量从缓冲池中刷新修改后的数据库页面。无需在单个批处理中刷新缓冲池,这会在检查点过程中中断用户SQL语句的处理。
InnoDB
在崩溃恢复期间,
InnoDB查找写入日志文件的检查点标签。它知道标签之前对数据库的所有修改都存在于数据库的磁盘映像中。然后InnoDB从检查点向前扫描日志文件,将已记录的修改应用到数据库。
随机插入或从辅助索引中删除可能导致索引变成碎片。碎片意味着磁盘上索引页的物理顺序不接近页面记录的索引排序,或者分配给索引的64页块中有很多未使用的页面。
碎片化的一个症状是,一张桌子比“ 应该 ”需要更多的空间。究竟是多少,难以确定。所有InnoDB数据和索引都存储在B树中,其填充因子可能在50%到100%之间变化。碎片的另一个症状是像这样的表扫描需要比“ 应该 ”更多的时间
:
SELECT COUNT(*)FROM t WHERE non_indexed_column<> 12345;
前面的查询要求MySQL执行全表扫描,这是大型表最慢的查询类型。
为了加速索引扫描,你可以定期执行一个
“ 空 ” ALTER TABLE
操作,这会导致MySQL重建表:
ALTER TABLE tbl_nameENGINE = INNODB
您也可以使用
执行重建表的
“ 空 ” alter操作。
ALTER TABLE
tbl_name FORCE
双方并
使用
在线DDL。有关更多信息,请参见第14.13.1节“在线DDL概述”。
ALTER TABLE
tbl_name ENGINE=INNODBALTER TABLE
tbl_name FORCE
执行碎片整理操作的另一种方法是使用 mysqldump将表转储到文本文件,删除表并从转储文件重新加载。
如果插入到索引中始终是升序并且只从最后删除记录,则InnoDB
文件空间管理算法可确保索引中的碎片不会发生。
当回收操作系统的磁盘空间
截断的
InnoDB表,该表必须存放在自己的的.ibd文件。要将表存储在其自己的.ibd
文件中,innodb_file_per_table必须在创建表时启用。另外,在被截断的表和其他表之间不能有
外键约束,否则
TRUNCATE TABLE操作失败。但是,同一个表中两列之间的外键约束是允许的。
当表被截断时,它将被删除并在新.ibd文件中重新创建
,并且释放的空间将返回到操作系统。这与截断InnoDB存储在
InnoDB
系统表空间
(表创建时的表innodb_file_per_table=OFF)和存储在共享
通用表空间中的表的对比
,其中只能InnoDB在截断表后使用释放的空间。
截断表和向操作系统返回磁盘空间的能力也意味着
物理备份可以更小。截断存储在系统表空间(当创建表时
innodb_file_per_table=OFF)或在常规表空间中的表时,会在表空间中留下未使用空间的块。
该InnoDB 在线DDL功能允许就地改建表或同时
DML,或两者兼而有之。此功能的好处包括:
在繁忙的生产环境中改进响应能力和可用性,使得桌子在几分钟或几小时内不可用。
在
使用子句的DDL操作期间调整性能和并发之间的平衡的能力LOCK。
LOCK=EXCLUSIVE 完全禁止访问表格。
LOCK=SHARED 允许查询但不包含DML。
LOCK=NONE 允许对表进行完整的查询和DML访问。
LOCK=DEFAULT或者LOCK根据DDL操作的类型省略该
子句允许尽可能多的并发性。
避免与复制表格和重建二级索引相关的磁盘空间使用情况和I / O开销。
在线DDL功能增强了以前需要在表格上进行表格复制或阻止DML操作的许多DDL操作,或两者兼而有之。表14.10“DDL操作的联机状态”显示了联机DDL功能如何应用于每个DDL语句。
除大多数ALTER
TABLE分区子句外,分区InnoDB表的联机DDL操作遵循适用于常规InnoDB表的相同规则。有关更多信息,请参见第14.13.7节“分区表的联机DDL”。
一些因素会影响在线DDL操作的性能,空间使用情况和语义。有关更多信息,请参见 第14.13.8节“在线DDL限制”。
该“ 就地?“列显示哪些操作允许该ALGORITHM=INPLACE子句。
在“ 重建表?“列显示哪些操作重建表。对于使用该INPLACE算法的操作,
表格已重建。对于不支持该
INPLACE算法的操作,表格复制方法用于重建表格。
该“ 许可证并发DML?“列显示哪些操作完全在线执行。您可以指定
LOCK=NONE在DDL操作期间声明允许并发DML。如果可能,MySQL会自动允许并发DML。
所有在线DDL操作都允许并发查询。您可以指定LOCK=SHARED在DDL操作期间声明允许并发查询。MySQL尽可能自动允许并发查询。
在“ 备注 ”栏提供了额外的信息,并说明有关的异常和依赖关系“ 是/否 ”等栏目的值。星号表示异常或依赖关系。
表14.10 DDL操作的联机状态
| 手术 | 到位? | 重建表格? | 允许并发DML? | 只修改元数据? | 笔记 |
|---|---|---|---|---|---|
CREATE INDEX,
ADD
INDEX |
是* | 没有* | 是 | 没有 | 限制适用于FULLTEXT指数; 见下一行。 |
ADD FULLTEXT
INDEX |
是* | 没有* | 没有 | 没有 | FULLTEXT如果没有用户定义的FTS_DOC_ID
列,添加第一个索引将重建表。后续FULLTEXT索引可能会添加到同一个表上而不重建表。 |
ADD SPATIAL INDEX |
是 | 没有 | 没有 | 没有 | |
RENAME INDEX |
是 | 没有 | 是 | 是 | 只修改表格元数据。 |
DROP INDEX |
是 | 没有 | 是 | 是 | 只修改表格元数据。 |
OPTIMIZE TABLE |
是* | 是 | 是 | 没有 | 具有FULLTEXT索引的表格不支持就地操作
。 |
| 设置列的默认值 | 是 | 没有 | 是 | 是 | 只修改表格元数据。 |
| 更改自动增量值 | 是 | 没有 | 是 | 没有* | 修改存储在内存中的值,而不是数据文件。 |
| 添加外键约束 | 是* | 没有 | 是 | 是 | 该INPLACE算法在foreign_key_checks禁用时受支持
。否则,只COPY
支持该算法。 |
| 删除外键约束 | 是 | 没有 | 是 | 是 | foreign_key_checks 可以启用或禁用。 |
| 重命名列 | 是* | 没有 | 是* | 是 | 要允许并发DML,请保持相同的数据类型并只更改列名称。ALGORITHM=INPLACE不支持重命名
生成的列。 |
| 添加列 | 是* | 是* | 是* | 没有 | 添加自动增量
列时,不允许并发DML
。数据被大量重组,使其成为一项昂贵的操作。ALGORITHM=INPLACE支持添加
虚拟生成列,但不支持添加
存储的生成列。添加虚拟生成的列不需要重建表。 |
| 删除列 | 是 | 是* | 是 | 没有 | 数据被大量重组,使其成为一项昂贵的操作。
ALGORITHM=INPLACE支持删除生成的列。删除
虚拟生成的列不需要重建表。 |
| 对列重新排序 | 是 | 是 | 是 | 没有 | 数据被大量重组,使其成为一项昂贵的操作。 |
更改ROW_FORMAT属性 |
是 | 是 | 是 | 没有 | 数据被大量重组,使其成为一项昂贵的操作。 |
更改KEY_BLOCK_SIZE属性 |
是 | 是 | 是 | 没有 | 数据被大量重组,使其成为一项昂贵的操作。 |
制作专栏 NULL |
是 | 是* | 是 | 没有 | 重建表格。数据被大量重组,使其成为一项昂贵的操作。 |
制作专栏 NOT NULL |
是* | 是 | 是 | 没有 | 重建表格。STRICT_ALL_TABLES或者
STRICT_TRANS_TABLES
SQL_MODE是操作成功所必需的。如果该列包含NULL值,则操作失败。服务器禁止更改可能导致引用完整性丢失的外键列。请参见第13.1.8节“ALTER TABLE语法”。数据被大量重组,使其成为一项昂贵的操作。 |
| 更改列数据类型 | 没有* | 是 | 没有 | 没有 | VARCHAR大小可能会增加使用在线ALTER TABLE。请参阅
修改列属性以获取更多信息。 |
| 添加主键 | 是* | 是* | 是 | 没有 | 重建表格。数据被大量重组,使其成为一项昂贵的操作。
ALGORITHM=INPLACE在某些条件下,如果需要将列转换为列,则不允许使用
NOT NULL。 |
| 删除主键并添加另一个 | 是 | 是 | 是 | 没有 | 数据被大量重组,使其成为一项昂贵的操作。 |
| 删除主键 | 没有 | 是 | 没有 | 没有 | 仅ALGORITHM=COPY支持在相同ALTER
TABLE语句中添加主键而不添加新键。 |
| 转换字符集 | 没有 | 是* | 没有 | 没有 | 如果新字符编码不同,则重建表格。 |
| 指定字符集 | 没有 | 是* | 没有 | 没有 | 如果新字符编码不同,则重建表格。 |
重建FORCE选项 |
是* | 是 | 是 | 没有 | 用途ALGORITHM=INPLACE。
ALGORITHM=INPLACE不支持带FULLTEXT索引的表。 |
“ null ”使用重建ALTER TABLE ...
ENGINE=INNODB |
是* | 是 | 是 | 没有 | 用途ALGORITHM=INPLACE。
ALGORITHM=INPLACE不支持带FULLTEXT索引的表。 |
集STATS_PERSISTENT,
STATS_AUTO_RECALC,
STATS_SAMPLE_PAGES
执着统计选项 |
是 | 没有 | 是 | 是 | 只修改表格元数据。 |
ALTER TABLE … ENCRYPTION |
没有 | 是 | 没有 | 是 | |
放下一STORED列 |
是 | 是* | 是 | 没有 | 重建表格。 |
修改STORED列顺序 |
是 | 是* | 是 | 没有 | 重建表格。 |
添加一STORED列 |
是 | 是* | 是 | 没有 | 重建表格。 |
放下一VIRTUAL列 |
是 | 没有 | 是 | 是 | |
修改VIRTUAL列顺序 |
是 | 没有 | 是 | 是 | |
添加一VIRTUAL列 |
是 | 没有 | 是 | 是 |
以下各节提供了各种在线DDL操作的基本语法和使用说明。
添加辅助索引:
CREATE INDEXnameONtable(col_list);
ALTER TABLEtableADD INDEXname(col_list);
删除辅助索引:
DROP INDEXnameONtable;
ALTER TABLEtableDROP INDEXname;
虽然不需要语法变化
CREATE INDEX或
DROP INDEX命令,一些因素会影响性能,空间使用,而这个操作的语义(见第14.13.8,“在线DDL限制”)。
在InnoDB表上创建和删除二级索引将
跳过表复制行为。
在创建或删除索引时,该表仍可用于读取和写入操作。在
CREATE INDEX或
DROP INDEX正在访问表中的所有交易完成后语句只完成,因此该指数的初始状态反映最近的表的内容。此前,修改表,同时索引被创建或通常下降导致了
僵局是取消了
INSERT,
UPDATE或者
DELETE声明在桌子上。
在线DDL支持添加二级索引意味着通常可以通过创建没有任何二级索引的表来加速创建和加载表和相关索引的整个过程,然后在加载数据后添加二级索引。
修改列的默认值:
ALTER TABLEtblALTER COLUMNcolSET DEFAULTliteral;
ALTER TABLEtblALTER COLUMNcolDROP DEFAULT;
更改列的 自动增量 值:
ALTER TABLEtableAUTO_INCREMENT =next_value;
特别是在使用复制或分片的分布式系统中,有时您会将表的自动增加计数器重置为特定值。插入到表中的下一行将为其自动增量列使用指定的值。您也可以在数据仓库环境中使用该技术,在该环境中定期清空所有表并重新加载它们,然后可以从1重新开始自动递增序列。
重命名一列:
ALTER TABLEtblCHANGE ;old_col_namenew_col_namedatatype
如果保持相同的数据类型和[NOT]
NULL属性,只更改列名称,则可始终在线执行此操作。
您还可以重命名属于外键约束的一列。外键定义自动更新为使用新的列名称。重命名参与外键的列仅适用于in-place模式ALTER TABLE。如果使用该ALGORITHM=COPY子句或其他一些条件导致该命令ALGORITHM=COPY在幕后使用
,则该
ALTER TABLE语句失败。
VARCHAR使用就地ALTER TABLE语句
扩展大小:
ALTER TABLE t1 ALGORITHM = INPLACE,CHANGE COLUMN c1 c1 VARCHAR(255);
VARCHAR列
所需的长度字节数
必须保持不变。对于VARCHAR0到255的值,需要一个长度字节来对该值进行编码。对于
VARCHAR256字节或更多的值,需要两个长度字节。因此,in-place
ALTER TABLE只支持VARCHAR从0到255个字节的增加VARCHAR大小或从等于或大于256个字节的值增加
大小。就地
ALTER TABLE不支持增加VARCHAR大小从小于256字节到等于或大于256字节的值。在这种情况下,所需的长度字节数将从1更改为2,这只能由表副本(ALGORITHM=COPY)支持。例如,试图VARCHAR使用in-place ALTER
TABLE将列大小从255 更改为256 会返回错误:
ALTER TABLE t1 ALGORITHM = INPLACE,CHANGE COLUMN c1 c1 VARCHAR(256); 错误0A000:ALGORITHM = INPLACE不受支持。原因:无法更改 列类型INPLACE。尝试ALGORITHM = COPY。
不支持VARCHAR使用in-place
减小大小ALTER TABLE。减小VARCHAR
大小需要一个表副本(ALGORITHM=COPY)。
添加或删除a 外键约束:
ALTER TABLEtbl1ADD CONSTRAINTfk_nameFOREIGN KEYindex(col1) 参考文献tbl2(col2)referential_actions;
ALTER TABLEtblDROP FOREIGN KEYfk_name;
通过foreign_key_checks启用或禁用选项,可以在线执行删除外键
。在线创建外键需要
foreign_key_checks被禁用。
如果您不知道特定表上外键约束的名称,请发出以下语句并在中找到约束名称 CONSTRAINT每个外键子句中:
SHOW CREATE TABLE table \ G
或者,查询
INFORMATION_SCHEMA.TABLE_CONSTRAINTS
表并使用CONSTRAINT_NAME和
CONSTRAINT_TYPE列标识外键名称。
您也可以在一个语句中删除一个外键及其关联的索引:
ALTER TABLEtableDROP FOREIGN KEYconstraint,DROP INDEXindex;
如果外键已经存在于被修改的表中(即它是一个包含
子句的
子表FOREIGN KEY ... REFERENCE),则对在线DDL操作(即使不是直接涉及外键列的操作)也会有其他限制:
一个ALTER TABLE子表上可以等待其他事务提交时,如果更改了父表通过引起子表的相关变化ON UPDATE或
ON DELETE使用子句
CASCADE或SET NULL
参数。
以同样的方式,如果表是
父表的外键关系,即使它不包含任何
FOREIGN KEY条款,它可以等待
ALTER TABLE完成如果一个
INSERT,
UPDATE或
DELETE语句会引起
ON UPDATE或ON DELETE
子表的行动。
随着数据库模式随着新列,数据类型,约束,索引等的发展而变化,请CREATE TABLE使用最新的表定义使语句保持
最新。即使在线DDL的性能有所提高,但在开始时创建稳定的数据库结构效率更高,而不是创建模式的一部分,然后再发布ALTER
TABLE语句。
此准则的主要例外是对 具有大量行的表的二级索引。通常,使用除辅助索引外的所有详细信息创建表,加载数据,然后创建辅助索引是最有效的。如果您知道初始数据是干净的并且在加载过程中不需要一致性检查,则可以使用与外键相同的技术 (首先加载数据,然后设置外键)。
无论序列CREATE TABLE,
CREATE INDEX,
ALTER TABLE,和类似表述走进了把一个表一起,你可以捕获通过发出声明,以重建表的当前形式所需的SQL (大写
为整齐的格式要求)。此输出显示子句,如数字精度,以及有时会添加到幕后,在克隆新系统上的表或设置具有相同类型的外键列时,可能不需要这些子句。
SHOW CREATE TABLE
table\G\GNOT
NULLCHARACTER SET
在线DDL改进了MySQL操作的几个方面,例如性能,并发性,可用性和可伸缩性:
如果在线操作需要临时排序文件,则
InnoDB默认在临时文件目录中创建它们,而不是包含原始表格的目录。如果此目录不足以容纳此类文件,则可能需要将tmpdir
系统变量设置为不同的目录。或者,您可以使用配置选项为InnoDB在线ALTER
TABLE操作
定义一个单独的临时目录
innodb_tmpdir。有关更多信息,请参阅
联机DDL操作的空间要求以及
第B.5.3.5节“MySQL存储临时文件的位置”。
虽然InnoDB表正在通过DDL操作进行更改,但根据该操作的内部工作原理和语句的
子句,该表可能锁定也可能不
锁定。默认情况下,在DDL操作期间,MySQL使用尽可能少的锁定; 您可以指定子句,以使锁定比通常情况下更具限制性(从而限制并发DML或DML和查询),或者确保某个操作允许某种预期锁定程度。如果子句指定的锁定级别不适用于该特定种类的DDL操作,如
orLOCKALTER
TABLELOCKLOCK=SHAREDLOCK=NONE
在创建或删除主键时,该子句像断言一样工作,导致语句失败并出现错误。以下列表显示了LOCK从最宽容到最严格的条款的不同可能性
:
对于DDL操作LOCK=NONE,允许查询和并发DML。ALTER TABLE如果无法使用所请求的锁定类型执行DDL操作,则此子句会导致失败,因此请指定LOCK=NONE保留表的完整可用性至关重要,如果无法取消DDL,则可以取消该DDL。例如,您可以在涉及客户注册或购买的表中使用DDL中的此子句,以避免错误地发出昂贵的ALTER TABLE声明而使这些表不可用
。
对于DDL操作LOCK=SHARED,对表的任何写入(即DML操作)都会被阻止,但可以读取表中的数据。ALTER TABLE如果不能使用所请求的锁定类型执行DDL操作,则此子句会导致
失败,因此请指定LOCK=SHARED保留可用于查询的表是否至关重要,如果无法取消DDL,则可以取消该DDL。例如,您可以在DDL中将此子句用于数据仓库中的表,可以将数据加载操作延迟到DDL完成,但查询不能长时间延迟。
对于带有LOCK=DEFAULT或LOCK省略该子句的DDL操作,MySQL使用可用于该类操作的最低级别的锁定,允许并发查询,DML或两者都尽可能。这是在进行预先规划的,预先测试过的变更时使用的设置,根据该表的工作负载,您知道这些变更不会导致任何可用性问题。
对于DDL操作LOCK=EXCLUSIVE,查询和DML操作都被阻止。ALTER TABLE如果使用所请求的类型的锁定无法执行DDL操作,则此子句会导致失败,因此请指定
LOCK=EXCLUSIVE主要关注点是否在尽可能最短的时间内完成DDL,并且可以让应用程序在尝试访问时等待桌子。LOCK=EXCLUSIVE
如果服务器应该处于空闲状态,也可以使用,以避免意外访问表。
在大多数情况下,表上的联机DDL操作会等待当前正在执行的正在访问表的事务
提交或
回滚,因为在准备DDL语句时,它需要在短时间内独占访问表。同样,在线DDL操作在完成之前需要短时间独占访问表。因此,联机DDL语句还等待在DDL正在执行时启动的事务在完成之前提交或回滚。因此,在执行插入,更新,删除或者长时间运行的事务的情况下SELECT ... FOR UPDATE对表进行操作时,可能会使在线DDL操作超时等待对表的独占访问。
在表中的联机DDL操作不等待当前正在执行的事务完成的情况下,当表处于外键关系并且事务在外键关系中的另一个表上显式运行时,可能会发生这种情况。在这种情况下,事务在它正在更新的表上保存一个独占的元数据锁,但仅InnoDB在另一个表上保存共享
表锁(用于外键检查)。共享
InnoDB表锁定允许联机DDL操作继续,但在专用阶段阻止提交阶段的操作InnoDB表锁是必需的。这种情况会导致死锁,因为其他事务等待在线DDL操作提交。(请参阅错误#48652和错误#77390)
因为记录并发DML操作所做的更改需要一些处理工作,所以在最后应用这些更改时,联机DDL操作可能比阻止其他会话访问表的旧式机制花费更长的时间。原始性能的降低与使用该表的应用程序的更好的响应性相平衡。在评估改变表格结构的理想技术时,根据诸如网页加载时间等因素考虑最终用户对性能的感知。
新创建的InnoDB二级索引只包含执行CREATE INDEX或
ALTER TABLE语句执行时表中的提交数据
。它不包含任何未提交的值,旧版本的值或标记为删除但尚未从旧索引移除的值。
在线DDL操作的原始性能很大程度上取决于操作是在原地执行还是需要复制和重建整个表格。请参阅 表14.10,“DDL操作的联机状态”,查看可以在何处执行的操作以及避免执行表复制操作的任何要求。
来自原地DDL的性能提速适用于二级索引上的操作,而不适用于主键索引。InnoDB表的行存储在 基于主键组织的 聚集索引中,形成一些数据库系统称为 “ 索引组织表 ”的内容。由于表结构与主键密切相关,重新定义主键仍然需要复制数据。
当主键上的操作使用时
ALGORITHM=INPLACE,即使数据仍被复制,它比使用效率更高,
ALGORITHM=COPY因为:
不需要撤消日志记录或关联的重做日志记录
ALGORITHM=INPLACE。这些操作会为使用的DDL语句增加开销
ALGORITHM=COPY。
辅助索引条目是预先排序的,因此可以按顺序加载。
不使用更改缓冲区,因为在辅助索引中没有随机访问插入。
为了判断在线DDL操作的相对性能,可以InnoDB使用当前版本和早期版本的MySQL 在大型表上运行这些操作。您还可以在最新的MySQL版本下运行所有性能测试,通过设置系统变量来模拟之前 “结果
”的 DDL行为
old_alter_table。set
old_alter_table=1在会议中发表声明,并衡量DDL表现以记录“ 之前 ”的数字。然后
set old_alter_table=0重新启用更新,更快的行为,并再次运行DDL操作以记录
“ 之后 ”数字。
有关DDL操作是在原地进行更改还是执行表副本的基本概念,请查看命令完成后显示的“ 受影响的行 ”值。例如,以下是执行不同类型的DDL操作后可能会看到的行:
更改列的默认值(超快速,根本不影响表数据):
查询OK,0行受影响(0.07秒)
添加一个索引(需要时间,但0 rows
affected显示表格未被复制):
查询OK,0行受影响(21.42秒)
更改列的数据类型(需要大量时间,并且需要重新构建表的所有行):
查询OK,1671168行受影响(1分35.54秒)
更改列的数据类型需要重新VARCHAR构建表的所有行,但可以使用联机更改
大小ALTER
TABLE。请参阅
修改列属性以获取更多信息。
例如,在大型表上运行DDL操作之前,可以按如下方式检查操作是快速还是慢速:
克隆表结构。
用少量数据填充克隆表。
在克隆的表上运行DDL操作。
检查“ rows affected ”值是否为零。非零值意味着操作需要重建整个表格,这可能需要特殊的计划。例如,您可以在计划停机时间段内或每次在一台复制从属服务器上执行DDL操作。
对于在MySQL处理的减少更深入的了解,检查performance_schema和
INFORMATION_SCHEMA相关的表格
InnoDB前,DDL操作后,看到许多物理读,写,内存分配,等等。
在线DDL操作具有以下空间要求:
临时日志文件的空间
对于正在创建的每个索引或正在更改的表,都有一个这样的日志文件。该日志文件存储在DDL操作期间插入,更新或删除的表中的数据。当需要时,临时日志文件将被扩展innodb_sort_buffer_size,直到达到最大值
innodb_online_alter_log_max_size。如果临时日志文件超过了大小上限,则
ALTER TABLE操作失败,所有未提交的并发DML操作都会回滚。因此,此选项的较大值允许在联机DDL操作期间发生更多DML,但是也可以延长DDL操作结束时的时间间隔,以便锁定表以应用日志中的数据。
如果该操作需要很长时间,并且DML并发地修改了该表,那么临时联机日志的大小超过了innodb_online_alter_log_max_size
配置选项的值
,则联机DDL操作将失败并显示
DB_ONLINE_LOG_TOO_BIG错误。
临时排序文件的空间
重建表的在线DDL操作将临时排序文件写入MySQL临时目录($TMPDIR在Unix
%TEMP%上,Windows上或由--tmpdir
配置变量)。每个临时排序文件都足够大,可以容纳为新的辅助索引定义的所有列以及作为聚簇索引主键一部分的列,并且每当临时排序文件合并到最终表或索引时就会被删除。这些操作可能需要临时空间等于表中数据量加上索引。如果操作使用数据目录(datadir)所在文件系统上的所有可用磁盘空间,则重建表的联机DDL操作可能会导致错误。
从MySQL 5.7.11开始,您可以使用
innodb_tmpdir配置选项为在线DDL操作定义一个单独的临时目录。innodb_tmpdir引入该
选项是为了避免在ALTER
TABLE重建表的联机操作期间创建的大型临时排序文件导致临时目录溢出。
中间表文件的空间
重建表的一些联机DDL操作会在与原始表相同的目录中创建临时中间表文件,而不是重新创建表。中间表文件可能需要的空间等于原始表的大小。在第14.13.1节“在线DDL概述”中记录了重建表的操作 。
通常,在使用表格语句
时
,您无需执行任何特殊的操作即可启用
联机DDL。请参阅
表14.10,“DDL操作的联机状态”,了解可以在原地执行的DDL操作类型,允许并发DML或两者。一些变化需要配置设置或子句的特定组合。
ALTER TABLEInnoDBALTER
TABLE
您可以通过控制特定的在线DDL操作的各个方面LOCK和
ALGORITHM该子句
ALTER TABLE声明。这些条款出现在声明的最后,并以逗号分隔列表和列规范。该LOCK
子句对于微调并发访问表的程度很有用。该ALGORITHM子句主要用于性能比较,以及在遇到与现有DDL代码有关的任何问题时作为旧表复制行为的回退。例如:
为避免意外使表不可用于读取,写入或两者,请在ALTER TABLE语句中指定一个子句
LOCK=NONE(如同时
允许读取和写入)或
LOCK=SHARED(允许读取)。如果请求的并发级别不可用,该操作会立即停止。
要比较性能,请使用ALGORITHM=INPLACE另一个
语句运行一个语句
ALGORITHM=COPY,作为设置old_alter_table
配置选项的替代方法。
为避免将服务器与ALTER TABLE复制表的操作捆绑在一起
,请包括
ALGORITHM=INPLACE。如果语句不能使用就地机制,该语句立即停止。请参阅
表14.10,“DDL操作的联机状态”,以获取可以或不可以在原地执行的DDL操作列表。
有关该子句的更多详细信息,
请参见第14.13.2节“在线DDL性能,并发性和空间要求”LOCK。
在引入在线DDL之前,将许多DDL操作合并为一个ALTER TABLE
语句是很常见的做法。因为每个ALTER TABLE
语句都涉及复制和重建表,所以一次对同一个表进行多次更改会更高效,因为这些更改都可以通过对表执行单个重建操作来完成。缺点是涉及DDL操作的SQL代码难以维护并在不同的脚本中重复使用。如果每次具体更改都不相同,则可能需要ALTER
TABLE为每个稍有不同的场景构建一个新的复合体。
对于可以在原地完成的DDL操作(如
表14.10“DDL操作的联机状态”所示),现在可以将它们分离为单独的ALTER
TABLE语句,以便于脚本编写和维护,而不会影响效率。例如,您可能会采取复杂的语句,例如:
ALTER TABLE t1 ADD INDEX i1(c1),ADD UNIQUE INDEX i2(c2), 更改c4_old_name c4_new_name INTEGER UNSIGNED;
并将其分解成可以独立测试和执行的更简单的部分,例如:
ALTER TABLE t1 ADD INDEX i1(c1); ALTER TABLE t1 ADD UNIQUE INDEX i2(c2); ALTER TABLE t1 CHANGE c4_old_name c4_new_name INTEGER UNSIGNED NOT NULL;
您可能仍然使用以下部分的多部分ALTER
TABLE语句:
必须以特定顺序执行的操作,例如创建索引后跟使用该索引的外键约束。
所有操作都使用相同的特定LOCK
条款,您希望成功或失败作为一个组。
无法在原地执行的操作,即仍然复制并重建表格的操作。
您指定的操作,
ALGORITHM=COPY或者
old_alter_table=1如果需要强制执行表复制行为,以便在特定方案中实现精确的向后兼容。
表格的
每项ALTER TABLE操作
InnoDB都受以下几个方面的控制:
表格的物理表示是否有任何改变,或者它是否完全改变元数据,而不用触摸表格本身。
表中的数据量是否保持不变,增加还是减少。
表数据的更改是涉及聚集索引,二级索引还是两者。
在被修改的表和其他表之间
是否有任何外键关系。根据foreign_key_checks
配置选项是启用还是禁用,机制有所不同。
表是否已分区。分区子句
ALTER TABLE变成涉及一个或多个表的低级操作,并且这些操作遵循在线DDL的常规规则。
是否必须复制表格数据,表格是否可以“ 就地 ”重组,或两者的组合。
该表是否包含任何 自动增量 列。
根据基础数据库操作的性质或您在
声明中指定的子句,需要
什么程度的锁定。
LOCKALTER TABLE
以下是在线DDL操作失败的主要原因:
如果一个LOCK子句指定了与特定类型的DDL操作不兼容的低度锁定(SHARED或NONE)。
如果tmpdir或
innodb_tmpdir文件系统运行的磁盘空间,而MySQL索引的创建过程中,在磁盘上写入临时排序文件。有关更多信息,请参见
第B.5.3.5节“MySQL存储临时文件的位置”。
如果ALTER TABLE花费这么长时间,并且DML同时修改表,那么临时在线日志的大小超过了innodb_online_alter_log_max_size
配置选项的值
。这种情况会导致
DB_ONLINE_LOG_TOO_BIG错误。
如果并发DML对原始表定义所允许的表进行更改,但不更改新表。当MySQL尝试应用来自并发DML语句的所有更改时,该操作仅在最后才会失败。例如,可以在创建唯一索引时将重复值插入列中,或者可以NULL在创建该列的主键索引时将
值插入
列中。并发DML所做的更改优先,并且ALTER TABLE
操作有效回滚。
尽管配置选项
innodb_file_per_table对InnoDB表的表示有显着影响,但
无论启用还是禁用该选项,以及该表是物理位于其自己的.ibd文件还是位于系统表空间内
,所有联机DDL操作都可以很好地工作
。
InnoDB有两种类型的索引: 表示表中所有数据的 聚集索引和可选的 二级索引加快查询速度。由于聚簇索引在其B树节点中包含数据值,因此添加或删除聚簇索引涉及到复制数据以及创建表的新副本。但是,辅助索引仅包含索引键和主键的值。可以在不复制聚簇索引中的数据的情况下创建或删除此类索引。因为每个辅助索引都包含主键值的副本(用于在需要时访问聚集索引),所以当您更改主键的定义时,也会重新创建所有辅助索引。
删除二级索引很简单。只更新内部的InnoDB系统表和MySQL数据字典表,以反映索引不再存在的事实。InnoDB将用于索引的存储返回到包含它的表空间,以便新索引或附加表行可以使用该空间。
要向现有表添加二级索引,InnoDB将扫描该表,并按次级索引键列的值依次使用内存缓冲区和临时文件对行进行排序。然后以键值顺序构建B树,这比以随机顺序将行插入索引更有效。由于B树节点在填充时会被拆分,因此以这种方式构建索引会使索引具有更高的填充因子,从而使后续访问的效率更高。
尽管在ALTER TABLE执行语句时服务器崩溃时不会丢失任何数据
,但
对于聚簇索引和
二级索引,崩溃恢复过程是不同的
。
如果服务器在创建InnoDB二级索引时崩溃,则在恢复时,MySQL将丢弃任何部分创建的索引。你必须重新运行ALTER TABLE或
CREATE INDEX声明。
在创建InnoDB聚簇索引期间发生崩溃时,恢复更为复杂,因为表中的数据必须复制到全新的聚簇索引中。请记住,所有InnoDB表都存储为聚簇索引。
MySQL通过将原始InnoDB表中的现有数据复制到具有所需索引结构的临时表来创建新的聚集索引。一旦数据被完全复制到这个临时表中,原始表就会被重新命名为一个不同的临时表名。包含新聚集索引的临时表将使用原始表的名称进行重命名,并从数据库中删除原始表。
如果在创建新的聚集索引时发生系统崩溃,则不会丢失任何数据,但必须使用过程中存在的临时表来完成恢复过程。由于很少重新创建聚簇索引或重新定义大型表上的主键,或者在此操作过程中遇到系统崩溃,因此本手册未提供有关从此方案中恢复的信息。
大多数ALTER TABLE分区子句不像普通的非分区InnoDB表一样经历相同的内部在线DDL API 。因此,对ALTER
TABLE分区子句的在线支持各不相同。
下表显示了每个ALTER TABLE分区语句的联机状态
。无论使用的在线DDL API如何,MySQL都会尝试尽可能减少数据复制和锁定。
该“ 就地?“列显示哪些操作允许该ALGORITHM=INPLACE子句。
该“ 许可证并发DML?“列显示哪些操作完全在线执行。您可以指定
LOCK=NONE在DDL操作期间声明允许并发DML。如果可能,MySQL会自动允许并发DML。
对于支持的操作,
ALGORITHM={COPY|INPLACE}可以指定
LOCK=SHARED在DDL操作期间声明允许并发查询。MySQL尽可能自动允许并发查询。
在“ 备注 ”栏提供了额外的信息,并说明有关的异常和依赖关系“ 是/否 ”等栏目的值。星号表示异常或依赖关系。
ALTER TABLE分区选项使用ALGORITHM=COPY或只允许
“ ALGORITHM=DEFAULT, LOCK=DEFAULT”,使用COPY算法重新分区表。换句话说,使用新的分区方案创建一个新的分区表。新创建的表包含由该ALTER TABLE
语句应用的所有更改,并将表数据复制到新的表结构中。
表14.11 ALTER TABLE分区子句的联机状态
| 分区子句 | 到位? | 允许并发DML? | 笔记 |
|---|---|---|---|
PARTITION BY |
没有 | 没有 | 许可证ALGORITHM=COPY,
LOCK={DEFAULT|SHARED|EXCLUSIVE} |
ADD PARTITION |
没有 | 没有 | 只允许ALGORITHM=DEFAULT,
LOCK=DEFAULT。不复制由RANGEor
分区的表的现有数据LIST。针对由HASHor
分区的表允许并发查询LIST。MySQL在持有共享锁的同时复制数据。 |
DROP PARTITION |
没有 | 没有 | 只允许ALGORITHM=DEFAULT,
LOCK=DEFAULT。不复制由RANGEor
分区的表的现有数据LIST。 |
DISCARD PARTITION |
没有 | 没有 | 只有许可证ALGORITHM=DEFAULT,
LOCK=DEFAULT |
IMPORT PARTITION |
没有 | 没有 | 只有许可证ALGORITHM=DEFAULT,
LOCK=DEFAULT |
TRUNCATE
PARTITION |
是 | 是 | 不复制现有数据。它只是删除行; 它不会改变表本身或其任何分区的定义。 |
COALESCE
PARTITION |
没有 | 没有 | 只允许ALGORITHM=DEFAULT,
LOCK=DEFAULT。并发查询被允许用于通过分区表HASH
或LIST,例如MySQL复制数据,而保持的共享锁。 |
REORGANIZE
PARTITION |
没有 | 没有 | 只允许ALGORITHM=DEFAULT,
LOCK=DEFAULT。针对由LINEAR
HASHor 分区的表允许并发查询LIST。MySQL在保存共享元数据锁的同时从受影响的分区复制数据。 |
EXCHANGE
PARTITION |
是 | 是 | |
ANALYZE PARTITION |
是 | 是 | |
CHECK PARTITION |
是 | 是 | |
OPTIMIZE
PARTITION |
没有 | 没有 | ALGORITHM和LOCK子句被忽略。重建整个表格。请参见
第22.3.4节“维护分区”。 |
REBUILD PARTITION |
没有 | 没有 | 只允许ALGORITHM=DEFAULT,
LOCK=DEFAULT。针对由LINEAR
HASHor 分区的表允许并发查询LIST。MySQL在保存共享元数据锁的同时从受影响的分区复制数据。 |
REPAIR PARTITION |
是 | 是 | |
REMOVE
PARTITIONING |
没有 | 没有 | 许可证ALGORITHM=COPY,
LOCK={DEFAULT|SHARED|EXCLUSIVE} |
ALTER TABLE
分区表上的
非分区联机操作遵循适用于常规表的相同规则。但是,ALTER
TABLE对每个表分区执行联机操作,由于在多个分区上执行操作,这会导致系统资源需求增加。
有关ALTER
TABLE分区子句的其他信息,请参见
分区选项和
第13.1.8.1节“ALTER TABLE分区操作”。有关一般分区的信息,请参见
第22章分区。
以下限制适用于在线DDL操作:
该表被复制,而不是在创建索引时使用快速索引创建TEMPORARY
TABLE。这已被报告为MySQL Bug#39833。
当用户试图删除外键所需的索引时,InnoDB处理错误情况。参见
第B.3节,“服务器错误代码和信息”的信息错误有关1553。
如果表中存在或有限制,则不允许使用
该ALTER TABLE子句
。
LOCK=NONEON...CASCADEON...SET
NULL
根据在线DDL操作的内部工作和声明的LOCK条款,在
ALTER TABLEDDL操作的初始阶段和最终阶段,在线DDL操作可能需要在短时间内独占访问表格。因此,如果在执行插入,更新,删除或SELECT ...
FOR UPDATE在表上执行长时间运行的事务,联机DDL操作可能会在完成之前等待; 如果在进行中启动类似的长时间运行事务,则在线DDL操作可能会在完成之前等待ALTER
TABLE。
在运行联机DDL操作时,运行ALTER TABLE语句的线程会
应用从其他连接线程同时在同一个表上运行的DML操作的“ 联机日志 ”。应用DML操作时,即使重复条目只是临时的,并且在“ 在线日志 ”中稍后输入时也会发生重复键入错误(错误1062(23000):重复条目)。这与外键约束检查的概念类似,在外键约束检查中
约束在事务期间必须保持。
InnoDB
OPTIMIZE TABLE将
InnoDB表映射到
ALTER TABLE操作以重建表并更新索引统计信息并释放聚簇索引中未使用的空间。二级索引的创建效率并不高,因为按照它们出现在主键中的顺序插入键。
OPTIMIZE TABLE通过添加在线DDL支持来重建常规InnoDB表和分区
表。有关更多信息,请参见第14.13.1节“在线DDL概述”。
InnoDBMySQL的5.6之前创建的表不支持ALTER
TABLE ... ALGORITHM=INPLACE针对包括时间列(表DATE,
DATETIME或
TIMESTAMP),并使用尚未重建
ALTER TABLE ...
ALGORITHM=COPY。在这种情况下,
ALTER TABLE ...
ALGORITHM=INPLACE操作返回以下错误:
错误1846(0A000):ALGORITHM = INPLACE不受支持。 原因:无法更改列类型INPLACE。尝试ALGORITHM = COPY。
这些限制通常适用于涉及表复制的大型表上的联机DDL操作:
没有任何机制可以暂停联机DDL操作或限制联机DDL操作的I / O或CPU使用率。
如果操作失败,则在线DDL操作的回滚可能很昂贵。
长时间运行的在线DDL操作可能会导致复制滞后。在主站上运行之前,在线DDL操作必须在主站上完成运行。此外,在主站上的DDL操作完成后(Bug#73196),在主站上同时处理的DML仅在从站上处理。
有关在大型表上运行联机DDL操作的其他信息,请参见 第14.13.2节“联机DDL性能,并发性和空间要求”。
系统变量是true或false可以在服务器启动时通过命名来启用,或者通过使用--skip-前缀来禁用
。例如,可以启用或禁用所述InnoDB自适应散列索引,则可以使用
--innodb_adaptive_hash_index或
--skip-innodb_adaptive_hash_index
在命令行上,或
innodb_adaptive_hash_index或
skip-innodb_adaptive_hash_index在选项文件。
带有数字值的系统变量可以
在命令行中
指定,也可以
在选项文件中指定。
--var_name=valuevar_name=value
许多系统变量可以在运行时更改(请参见 第5.1.6.2节“动态系统变量”)。
有关GLOBAL和
SESSION变量范围修饰符的信息,请参阅
SET
语句文档。
某些选项控制InnoDB数据文件的位置和布局
。
第14.6.1节“InnoDB启动配置”介绍了如何使用这些选项。
有些选项最初可能不会使用,它可以InnoDB根据机器容量和数据库工作负载来调整
性能特征
。
有关指定选项和系统变量的更多信息,请参见第4.2.3节“指定程序选项”。
表14.12 InnoDB选项和变量引用
| 属性 | 值 |
|---|---|
| 命令行格式 | --ignore-builtin-innodb |
| 弃用 | 是 |
| 系统变量 | ignore_builtin_innodb |
| 范围 | 全球 |
| 动态 | 没有 |
| 类型 | 布尔 |
在MySQL 5.1中,这个选项导致服务器表现得好像内置InnoDB不存在一样,这使得它InnoDB Plugin可以被使用。在MySQL 5.7中,InnoDB
它是默认的存储引擎,InnoDB
Plugin并未被使用,所以这个选项被忽略。
| 属性 | 值 |
|---|---|
| 命令行格式 | --innodb[=value] |
| 弃用 | 5.7.5 |
| 类型 | 列举 |
| 默认 | ON |
| 有效值 |
|
控制InnoDB存储引擎的加载(如果服务器是使用InnoDB支持编译的)
。此选项有三态格式,可能值OFF,
ON或FORCE。请参见
第5.5.1节“安装和卸载插件”。
禁用InnoDB,使用
--innodb=OFF
或
--skip-innodb。在这种情况下,因为默认的存储引擎是
InnoDB,服务器不会启动,除非您还使用
--default-storage-engine并将
--default-tmp-storage-engine默认设置为永久和TEMPORARY表的其他引擎的默认值
。
该InnoDB存储引擎可以不再被禁止,并且
--innodb=OFF
和
--skip-innodb
选项弃用,没有任何效果。他们的使用导致警告。这些选项将在未来的MySQL版本中被删除。
| 属性 | 值 |
|---|---|
| 命令行格式 | --innodb-status-file |
| 类型 | 布尔 |
| 默认 | OFF |
控制是否InnoDB创建一个
在MySQL数据目录中命名的文件
。如果启用,则
定期写入输出
innodb_status.pidInnoDBSHOW ENGINE
INNODB STATUS该文件。
默认情况下,该文件未被创建。要创建它,请使用该
选项启动
mysqld--innodb-status-file=1。该文件在正常关机期间被删除。
禁用InnoDB存储引擎。请参阅说明--innodb。
daemon_memcached_enable_binlog
| 属性 | 值 |
|---|---|
| 命令行格式 | --daemon-memcached-enable-binlog=# |
| 系统变量 | daemon_memcached_enable_binlog |
| 范围 | 全球 |
| 动态 | 没有 |
| 类型 | 布尔 |
| 默认 | false |
在主服务器上启用此选项
以将InnoDB memcached
插件(daemon_memcached)与MySQL
二进制日志一起使用。该选项只能在服务器启动时设置。您还必须使用。在主服务器上启用MySQL二进制日志
--log-bin选项。
有关更多信息,请参见 第14.20.6节“InnoDB memcached插件和复制”。
daemon_memcached_engine_lib_name
| 属性 | 值 |
|---|---|
| 命令行格式 | --daemon-memcached-engine-lib-name=library |
| 系统变量 | daemon_memcached_engine_lib_name |
| 范围 | 全球 |
| 动态 | 没有 |
| 类型 | 文件名 |
| 默认 | innodb_engine.so |
指定实现InnoDB memcached插件的共享库
。
有关更多信息,请参见 第14.20.3节“设置InnoDB memcached插件”。
daemon_memcached_engine_lib_path
| 属性 | 值 |
|---|---|
| 命令行格式 | --daemon-memcached-engine-lib-path=directory |
| 系统变量 | daemon_memcached_engine_lib_path |
| 范围 | 全球 |
| 动态 | 没有 |
| 类型 | 目录名称 |
| 默认 | NULL |
包含实现InnoDB
memcached插件的共享库的目录的路径。默认值为NULL,表示MySQL插件目录。除非memcached为位于MySQL插件目录之外的其他存储引擎指定插件,否则不需要修改此参数
。
有关更多信息,请参见 第14.20.3节“设置InnoDB memcached插件”。
| 属性 | 值 |
|---|---|
| 命令行格式 | --daemon-memcached-option=options |
| 系统变量 | daemon_memcached_option |
| 范围 | 全球 |
| 动态 | 没有 |
| 类型 | 串 |
| 默认 | |
用于在启动时将空格分隔的memcached选项传递到底层的memcached内存对象缓存守护进程。例如,您可能会更改memcached的端口 侦听,减少同时连接的最大数量,更改键/值对的最大内存大小或启用错误日志的调试消息。
有关使用细节,请参见第14.20.3节“设置InnoDB memcached插件”。有关memcached 选项的信息,请参阅memcached手册页。
| 属性 | 值 |
|---|---|
| 命令行格式 | --daemon-memcached-r-batch-size=# |
| 系统变量 | daemon_memcached_r_batch_size |
| 范围 | 全球 |
| 动态 | 没有 |
| 类型 | 整数 |
| 默认 | 1 |
指定在开始新事务之前要执行多少个memcached读取操作(get操作)COMMIT。对应的
daemon_memcached_w_batch_size。
默认情况下,此值设置为1,以便通过SQL语句对表进行的任何更改对memcached操作立即可见 。您可以增加它以减少系统中频繁提交的开销,因为系统只能通过memcached接口访问基础表 。如果设置的值太大,撤消或重做数据量可能会导致一些存储开销,就像任何长时间运行的事务一样。
有关更多信息,请参见 第14.20.3节“设置InnoDB memcached插件”。
| 属性 | 值 |
|---|---|
| 命令行格式 | --daemon-memcached-w-batch-size=# |
| 系统变量 | daemon_memcached_w_batch_size |
| 范围 | 全球 |
| 动态 | 没有 |
| 类型 | 整数 |
| 默认 | 1 |
指定多少memcached的写操作,如add,
set和incr,做一个前执行COMMIT
,以启动新的事务。对应的
daemon_memcached_r_batch_size。
默认情况下,此值设置为1,假设存储的数据对于在发生中断时保存很重要,并应立即执行。存储非关键数据时,可以增加此值以减少频繁落实的开销; 但N如果发生崩溃,最后的
-1个未提交的写入操作可能会丢失。
有关更多信息,请参见 第14.20.3节“设置InnoDB memcached插件”。
| 属性 | 值 |
|---|---|
| 命令行格式 | --ignore-builtin-innodb |
| 弃用 | 是 |
| 系统变量 | ignore_builtin_innodb |
| 范围 | 全球 |
| 动态 | 没有 |
| 类型 | 布尔 |
请参阅本节前面的“ InnoDB命令选项 ”--ignore-builtin-innodb下
的说明
。
| 属性 | 值 |
|---|---|
| 命令行格式 | --innodb-adaptive-flushing=# |
| 系统变量 | innodb_adaptive_flushing |
| 范围 | 全球 |
| 动态 | 是 |
| 类型 | 布尔 |
| 默认 | ON |
指定是否动态调整冲洗速度
脏页在
InnoDB
缓冲池中,根据工作负载。动态调整冲刷速率旨在避免I / O活动的爆发。该设置默认启用。有关更多信息,请参见
第14.6.3.6节“配置InnoDB缓冲池刷新”。有关通用I / O优化建议,请参见
第8.5.8节“优化InnoDB磁盘I / O”。
| 属性 | 值 |
|---|---|
| 命令行格式 | --innodb-adaptive-flushing-lwm=# |
| 系统变量 | innodb_adaptive_flushing_lwm |
| 范围 | 全球 |
| 动态 | 是 |
| 类型 | 整数 |
| 默认 | 10 |
| 最低限度 | 0 |
| 最大 | 70 |
定义表示启用自适应刷新的重做日志容量百分比的低水位标记 。有关更多信息,请参见 第14.6.3.7节“微调InnoDB缓冲池刷新”。
| 属性 | 值 |
|---|---|
| 命令行格式 | --innodb-adaptive-hash-index=# |
| 系统变量 | innodb_adaptive_hash_index |
| 范围 | 全球 |
| 动态 | 是 |
| 类型 | 布尔 |
| 默认 | ON |
无论是InnoDB
适应性的散列索引被启用或禁用。根据您的工作负载,可能需要动态启用或禁用
自适应哈希索引以提高查询性能。由于自适应散列索引可能并不适用于所有工作负载,因此可以使用实际的工作负载对启用和禁用的基准进行基准测试。有关详细信息,请参见
第14.4.3节“自适应散列索引”。
这个变量是默认启用的。您可以使用该SET GLOBAL语句修改此参数,而无需重新启动服务器。更改设置需要SUPER特权。您也可以--skip-innodb_adaptive_hash_index在服务器启动时使用
它来禁用它。
禁用自适应散列索引会立即清空散列表。正常操作可以在哈希表清空时继续,并且执行使用哈希表的查询直接访问索引B树。当自适应散列索引重新启用时,在正常操作期间再次填充散列表。
innodb_adaptive_hash_index_parts
| 属性 | 值 |
|---|---|
| 命令行格式 | --innodb-adaptive-hash-index-parts=# |
| 介绍 | 5.7.8 |
| 系统变量 | innodb_adaptive_hash_index_parts |
| 范围 | 全球 |
| 动态 | 没有 |
| 类型 | 数字 |
| 默认 | 8 |
| 最低限度 | 1 |
| 最大 | 512 |
划分自适应哈希索引搜索系统。每个索引都绑定到一个特定的分区,每个分区受独立的锁存器保护。
在早期版本中,自适应散列索引搜索系统受单个锁存器(btr_search_latch)的保护,该锁存器可能成为争用点。通过引入该
innodb_adaptive_hash_index_parts选项,默认情况下,搜索系统分为8个部分。最大设置是512。
相关信息请参见 第14.4.3节“自适应哈希索引”。
innodb_adaptive_max_sleep_delay
| 属性 | 值 |
|---|---|
| 命令行格式 | --innodb-adaptive-max-sleep-delay=# |
| 系统变量 | innodb_adaptive_max_sleep_delay |
| 范围 | 全球 |
| 动态 | 是 |
| 类型 | 整数 |
| 默认 | 150000 |
| 最低限度 | 0 |
| 最大 | 1000000 |
允许根据当前工作量InnoDB自动调整innodb_thread_sleep_delay向上或向下的值
。任何非零值都可以自动动态调整该
innodb_thread_sleep_delay值,直到innodb_adaptive_max_sleep_delay选项中指定的最大值
。该值表示微秒数。这个选项在繁忙的系统中可用,有超过16个
InnoDB线程。(实际上,它对于具有数百或数千个同时连接的MySQL系统是最有价值的。)
有关更多信息,请参见 第14.6.6节“为InnoDB配置线程并发”。
innodb_additional_mem_pool_size
| 属性 | 值 |
|---|---|
| 命令行格式 | --innodb-additional-mem-pool-size=# |
| 弃用 | 是(在5.7.4中删除) |
| 系统变量 | innodb_additional_mem_pool_size |
| 范围 | 全球 |
| 动态 | 没有 |
| 类型 | 整数 |
| 默认 | 8388608 |
| 最低限度 | 2097152 |
| 最大 | 4294967295 |
内存池的字节大小InnoDB
用于存储数据字典信息和其他内部数据结构。您在应用程序中拥有的表格越多,您在此分配的内存就越多。如果InnoDB
此池中的内存不足,它将开始从操作系统分配内存,并将警告消息写入MySQL错误日志。默认值是8MB。
这个变量与InnoDB
内部存储器分配器有关,如果innodb_use_sys_malloc被启用,它是未使用的
。有关更多信息,请参见
第14.6.4节“为InnoDB配置内存分配器”。
| 属性 | 值 |
|---|---|
| 命令行格式 | --innodb-api-bk-commit-interval=# |
| 系统变量 | innodb_api_bk_commit_interval |
| 范围 | 全球 |
| 动态 | 是 |
| 类型 | 整数 |
| 默认 | 5 |
| 最低限度 | 1 |
| 最大 | 1073741824 |
几秒钟内
自动提交使用InnoDB memcached接口的空闲连接的频率
。有关更多信息,请参见
第14.20.5.4节“控制InnoDB memcached插件的事务行为”。
| 属性 | 值 |
|---|---|
| 命令行格式 | --innodb-api-disable-rowlock=# |
| 系统变量 | innodb_api_disable_rowlock |
| 范围 | 全球 |
| 动态 | 没有 |
| 类型 | 布尔 |
| 默认 | OFF |
当InnoDB memcached
执行DML操作时,使用此选项可禁用行锁
。默认情况下,
innodb_api_disable_rowlock被禁用,这意味着memcached请求行锁get和set
操作。当innodb_api_disable_rowlock
启用时,分布式缓存请求表锁,而不是行锁。
innodb_api_disable_rowlock不是动态的。它必须在mysqld命令行中指定或输入到MySQL配置文件中。插件安装时配置生效,这在MySQL服务器启动时发生。
有关更多信息,请参见 第14.20.5.4节“控制InnoDB memcached插件的事务行为”。
| 属性 | 值 |
|---|---|
| 命令行格式 | --innodb-api-enable-binlog=# |
| 系统变量 | innodb_api_enable_binlog |
| 范围 | 全球 |
| 动态 | 没有 |
| 类型 | 布尔 |
| 默认 | OFF |
让您使用带有MySQL 二进制日志的InnoDB
memcached插件
。有关更多信息,请参阅
启用InnoDB memcached二进制日志。
| 属性 | 值 |
|---|---|
| 命令行格式 | --innodb-api-enable-mdl=# |
| 系统变量 | innodb_api_enable_mdl |
| 范围 | 全球 |
| 动态 | 没有 |
| 类型 | 布尔 |
| 默认 | OFF |
锁定InnoDB
memcached插件使用的表,以便它不能被DDL
通过SQL接口删除或更改。有关更多信息,请参见
第14.20.5.4节“控制InnoDB memcached插件的事务行为”。
| 属性 | 值 |
|---|---|
| 命令行格式 | --innodb-api-trx-level=# |
| 系统变量 | innodb_api_trx_level |
| 范围 | 全球 |
| 动态 | 是 |
| 类型 | 整数 |
| 默认 | 0 |
控制由memcached 接口处理的查询的事务 隔离级别。常用名称对应的常量是:
0 = READ UNCOMMITTED
1 = READ COMMITTED
2 = REPEATABLE READ
3 = SERIALIZABLE
有关更多信息,请参见 第14.20.5.4节“控制InnoDB memcached插件的事务行为”。
| 属性 | 值 |
|---|---|
| 命令行格式 | --innodb-autoextend-increment=# |
| 系统变量 | innodb_autoextend_increment |
| 范围 | 全球 |
| 动态 | 是 |
| 类型 | 整数 |
| 默认 | 64 |
| 最低限度 | 1 |
| 最大 | 1000 |
用于在自动扩展InnoDB
系统表空间文件变满时扩展大小的增量大小(以兆字节为单位)。缺省值为64.有关信息,请参阅
系统表空间数据文件配置和
第14.7.1节“调整InnoDB系统表空间大小”。
该
innodb_autoextend_increment
设置不会影响
文件每表的表
空间文件或
常规表空间文件。无论innodb_autoextend_increment
设置如何,这些文件都是自动扩展的
。最初的扩展是少量的,之后扩展以4MB为增量进行。
| 属性 | 值 |
|---|---|
| 命令行格式 | --innodb-autoinc-lock-mode=# |
| 系统变量 | innodb_autoinc_lock_mode |
| 范围 | 全球 |
| 动态 | 没有 |
| 类型 | 整数 |
| 默认 | 1 |
| 有效值 |
|
用于生成 自动增量 值 的锁定模式。传统,连续或交错的允许值分别为0,1或2。默认设置是1(连续)。有关每种锁定模式的特性,请参阅InnoDB AUTO_INCREMENT锁定模式。
innodb_background_drop_list_empty
| 属性 | 值 |
|---|---|
| 命令行格式 | --innodb-background-drop-list-empty=# |
| 介绍 | 5.7.10 |
| 系统变量 | innodb_background_drop_list_empty |
| 范围 | 全球 |
| 动态 | 是 |
| 类型 | 布尔 |
| 默认 | OFF |
启用
innodb_background_drop_list_empty调试选项有助于避免测试用例失败,方法是延迟表创建,直到背景下拉列表为空。例如,如果测试用例A将表t1放置在背景下拉列表中,则测试用例B将等待,直到创建表之前背景下拉列表为空
t1。
| 属性 | 值 |
|---|---|
| 命令行格式 | --innodb-buffer-pool-chunk-size |
| 介绍 | 5.7.5 |
| 系统变量 | innodb_buffer_pool_chunk_size |
| 范围 | 全球 |
| 动态 | 没有 |
| 类型 | 整数 |
| 默认 | 134217728 |
| 最低限度 | 1048576 |
| 最大 | innodb_buffer_pool_size / innodb_buffer_pool_instances |
innodb_buffer_pool_chunk_size定义InnoDB缓冲池调整大小操作的块大小。该
innodb_buffer_pool_size
参数是动态的,它允许您在不重新启动服务器的情况下调整缓冲池的大小。
为避免在调整大小操作期间复制所有缓冲池页面,操作在“ 块 ”中执行
。默认情况下,
innodb_buffer_pool_chunk_size是128MB(134217728字节)。块中包含的页数取决于值
innodb_page_size。
innodb_buffer_pool_chunk_size可以以1MB(1048576字节)为单位增加或减少。
更改该innodb_buffer_pool_chunk_size
值时适用以下条件
:
如果
innodb_buffer_pool_chunk_size*
innodb_buffer_pool_instances
大于缓冲池初始化时的当前缓冲池大小,
innodb_buffer_pool_chunk_size
则会截断为
innodb_buffer_pool_size/
innodb_buffer_pool_instances。
缓冲池大小必须始终等于或innodb_buffer_pool_chunk_size
*
的倍数
innodb_buffer_pool_instances。如果更改
innodb_buffer_pool_chunk_size,
innodb_buffer_pool_size
将自动调整为等于或
不小于当前缓冲池大小的innodb_buffer_pool_chunk_size
*
的倍数
innodb_buffer_pool_instances。调整发生在缓冲池初始化时。
更改时应小心
innodb_buffer_pool_chunk_size,因为更改此值可自动增加缓冲池的大小。在更改之前
innodb_buffer_pool_chunk_size,计算它将会产生的影响,
innodb_buffer_pool_size以确保生成的缓冲池大小可以接受。
为避免潜在的性能问题,块(innodb_buffer_pool_size/
innodb_buffer_pool_chunk_size)的数量不应超过1000个。
有关更多信息,请参见第14.6.3.2节“配置InnoDB缓冲池大小”。
innodb_buffer_pool_dump_at_shutdown
| 属性 | 值 |
|---|---|
| 命令行格式 | --innodb-buffer-pool-dump-at-shutdown=# |
| 系统变量 | innodb_buffer_pool_dump_at_shutdown |
| 范围 | 全球 |
| 动态 | 是 |
| 类型 | 布尔 |
| 默认(> = 5.7.7) | ON |
| 默认(<= 5.7.6) | OFF |
指定在MySQL服务器关闭时是否记录InnoDB
缓冲池中缓存的页面
,以缩短下次重新启动时的
预热过程。通常与...结合使用
innodb_buffer_pool_load_at_startup。该
innodb_buffer_pool_dump_pct
选项定义要转储的最近使用的缓冲池页面的百分比。
双方
innodb_buffer_pool_dump_at_shutdown
并innodb_buffer_pool_load_at_startup默认启用。
有关更多信息,请参见 第14.6.3.8节“保存和恢复缓冲池状态”。
| 属性 | 值 |
|---|---|
| 命令行格式 | --innodb-buffer-pool-dump-now=# |
| 系统变量 | innodb_buffer_pool_dump_now |
| 范围 | 全球 |
| 动态 | 是 |
| 类型 | 布尔 |
| 默认 | OFF |
立即记录在InnoDB
缓冲池中缓存的页面
。通常与...结合使用
innodb_buffer_pool_load_now。
有关更多信息,请参见 第14.6.3.8节“保存和恢复缓冲池状态”。
| 属性 | 值 |
|---|---|
| 命令行格式 | --innodb-buffer-pool-dump-pct=# |
| 介绍 | 5.7.2 |
| 系统变量 | innodb_buffer_pool_dump_pct |
| 范围 | 全球 |
| 动态 | 是 |
| 类型 | 整数 |
| 默认(> = 5.7.7) | 25 |
| 默认(<= 5.7.6) | 100 |
| 最低限度 | 1 |
| 最大 | 100 |
指定每个缓冲池读出和转储的最近使用页面的百分比。范围是1到100.默认值是25.例如,如果有4个缓冲池,每个缓冲池包含100个页面,并且
innodb_buffer_pool_dump_pct
设置为25,则将从每个缓冲池中转储25个最近使用的页面。
对
innodb_buffer_pool_dump_pct
默认值的更改与innodb_buffer_pool_dump_at_shutdown
and的
缺省值更改一致
innodb_buffer_pool_load_at_startup,这两个选项在MySQL 5.7中均默认启用。
| 属性 | 值 |
|---|---|
| 命令行格式 | --innodb-buffer-pool-filename=file |
| 系统变量 | innodb_buffer_pool_filename |
| 范围 | 全球 |
| 动态 | 是 |
| 类型 | 文件名 |
| 默认 | ib_buffer_pool |
指定保存由innodb_buffer_pool_dump_at_shutdown
or
生成的表空间ID和页面ID列表的文件的名称
innodb_buffer_pool_dump_now。表空间ID和页面ID以以下格式保存:
space, page_id。默认情况下,该文件被命名ib_buffer_pool并位于InnoDB数据目录中。必须指定相对于数据目录的非默认位置。
可以在运行时使用SET
语句指定文件名称
:
SET GLOBAL innodb_buffer_pool_filename = 'file_name';
您还可以在启动时在启动字符串或MySQL配置文件中指定文件名。在启动时指定文件名时,该文件必须存在或
InnoDB将返回启动错误,指示没有此文件或目录。
有关更多信息,请参见 第14.6.3.8节“保存和恢复缓冲池状态”。
| 属性 | 值 |
|---|---|
| 命令行格式 | --innodb-buffer-pool-instances=# |
| 系统变量 | innodb_buffer_pool_instances |
| 范围 | 全球 |
| 动态 | 没有 |
| 类型(其他) | 整数 |
| 类型(Windows,32位平台) | 整数 |
| 默认(其他) | 8 (or 1 if innodb_buffer_pool_size < 1GB |
| 默认(Windows,32位平台) | (autosized) |
| 最小(其他) | 1 |
| 最低(Windows,32位平台) | 1 |
| 最大(其他) | 64 |
| 最大(Windows,32位平台) | 64 |
InnoDB
缓冲池划分
的区域数量。对于缓冲池在数GB范围内的系统,通过在不同线程读取和写入缓存页面时减少争用,将缓冲池划分为不同的实例可以提高并发性。存储在缓冲池中或从中读取的每个页面都使用散列函数随机分配给其中一个缓冲池实例。每个缓冲池管理自己的空闲列表,
刷新列表,
LRU以及连接到缓冲池的所有其他数据结构,并受其自己的缓冲池互斥锁保护。
此选项仅在设置innodb_buffer_pool_size为1GB或更大时才有效
。总缓冲池大小在所有缓冲池中分配。为了获得最佳效率,指定的组合
innodb_buffer_pool_instances
和innodb_buffer_pool_size
,使得每个缓冲池实例是至少为1GB。
如下所述,32位Windows系统上的默认值取决于值
innodb_buffer_pool_size:
如果
innodb_buffer_pool_size
大于1.3GB,则默认
innodb_buffer_pool_instances
值为
innodb_buffer_pool_size/ 128MB,并为每个块分配单独的内存分配请求。选择1.3GB作为边界时存在32位Windows无法分配单个缓冲池所需的连续地址空间的重大风险。
否则,默认值为1。
在所有其他平台上,当innodb_buffer_pool_size大于或等于1GB 时,默认值为8
。否则,默认值为1。
相关信息请参见 14.6.3.2节“配置InnoDB缓冲池大小”。
| 属性 | 值 |
|---|---|
| 命令行格式 | --innodb-buffer-pool-load-abort=# |
| 系统变量 | innodb_buffer_pool_load_abort |
| 范围 | 全球 |
| 动态 | 是 |
| 类型 | 布尔 |
| 默认 | OFF |
中断恢复由
或
触发的InnoDB
缓冲池内容
的过程。
innodb_buffer_pool_load_at_startupinnodb_buffer_pool_load_now
有关更多信息,请参见 第14.6.3.8节“保存和恢复缓冲池状态”。
innodb_buffer_pool_load_at_startup
| 属性 | 值 |
|---|---|
| 命令行格式 | --innodb-buffer-pool-load-at-startup=# |
| 系统变量 | innodb_buffer_pool_load_at_startup |
| 范围 | 全球 |
| 动态 | 没有 |
| 类型 | 布尔 |
| 默认(> = 5.7.7) | ON |
| 默认(<= 5.7.6) | OFF |
指定在MySQL服务器启动时,通过加载它在先前保存的相同页面,
InnoDB
缓冲池自动预热。通常与...结合使用
innodb_buffer_pool_dump_at_shutdown。
双方
innodb_buffer_pool_dump_at_shutdown
并innodb_buffer_pool_load_at_startup默认启用。
有关更多信息,请参见 第14.6.3.8节“保存和恢复缓冲池状态”。
| 属性 | 值 |
|---|---|
| 命令行格式 | --innodb-buffer-pool-load-now=# |
| 系统变量 | innodb_buffer_pool_load_now |
| 范围 | 全球 |
| 动态 | 是 |
| 类型 | 布尔 |
| 默认 | OFF |
立即升温的
InnoDB
缓冲池通过装载一组数据页面,无需等待服务器重新启动。在基准测试期间将高速缓存恢复到已知状态,或者在运行查询报告或维护后,使MySQL服务器恢复正常工作负载,可能会很有用。
有关更多信息,请参见 第14.6.3.8节“保存和恢复缓冲池状态”。
| 属性 | 值 |
|---|---|
| 命令行格式 | --innodb-buffer-pool-size=# |
| 系统变量 | innodb_buffer_pool_size |
| 范围 | 全球 |
| 动态(> = 5.7.5) | 是 |
| 动态(<= 5.7.4) | 没有 |
| 类型(64位平台) | 整数 |
| 类型(32位平台) | 整数 |
| 默认(64位平台) | 134217728 |
| 默认(32位平台) | 134217728 |
| 最低(64位平台) | 5242880 |
| 最低(32位平台) | 5242880 |
| 最大(64位平台) | 2**64-1 |
| 最大(32位平台) | 2**32-1 |
缓冲池的
字节大小
,InnoDB缓存表和索引数据的内存区域。默认值是134217728字节(128MB)。最大值取决于CPU架构; 32位系统上的最大值为4294967295(2 32 -1),64位系统上的最大值为18446744073709551615(2 64 -1)。在32位系统上,CPU架构和操作系统可能会施加比实际最大值更小的实际最大值。当缓冲池的大小大于1GB时,设置
innodb_buffer_pool_instances
为大于1的值可以提高繁忙服务器的可伸缩性。
较大的缓冲池需要较少的磁盘I / O才能多次访问相同的表数据。在专用数据库服务器上,您可以将缓冲池大小设置为机器物理内存大小的80%。配置缓冲池大小时请注意以下潜在问题,并准备在必要时缩小缓冲池的大小。
物理内存竞争可能导致操作系统中的分页。
InnoDB 为缓冲区和控制结构保留额外的内存,因此总分配空间大约比指定的缓冲池大小大10%。
缓冲池的地址空间必须是连续的,这可能是在装有特定地址的DLL的Windows系统上的一个问题。
初始化缓冲池的时间大致与其大小成正比。在具有大缓冲池的实例上,初始化时间可能很重要。为了减少初始化时间,可以在服务器关闭时保存缓冲池状态,并在服务器启动时恢复它。请参见第14.6.3.8节“保存和恢复缓冲池状态”。
当您增加或减少缓冲池大小时,操作以块为单位执行。块大小由innodb_buffer_pool_chunk_size
配置选项定义
,其默认值为128 MB。
缓冲池大小必须始终等于或innodb_buffer_pool_chunk_size
*
的倍数
innodb_buffer_pool_instances。如果将缓冲池大小更改为不等于或等于innodb_buffer_pool_chunk_size
*
倍数的
innodb_buffer_pool_instances值,则会自动将缓冲池大小调整为等于或
不小于指定缓冲池大小的innodb_buffer_pool_chunk_size
*
的倍数
innodb_buffer_pool_instances。
innodb_buffer_pool_size可以动态设置,这允许您在不重新启动服务器的情况下调整缓冲池的大小。该
Innodb_buffer_pool_resize_status
状态变量报告在线缓冲池的大小调整操作的状态。有关更多信息,请参见
第14.6.3.2节“配置InnoDB缓冲池大小”。
| 属性 | 值 |
|---|---|
| 命令行格式 | --innodb-change-buffer-max-size=# |
| 系统变量 | innodb_change_buffer_max_size |
| 范围 | 全球 |
| 动态 | 是 |
| 类型 | 整数 |
| 默认 | 25 |
| 最低限度 | 0 |
| 最大 | 50 |
InnoDB
更改缓冲区的
最大大小,占缓冲池总大小的百分比
。您可能会增加MySQL服务器的这个数值,导致插入,更新和删除活动过多,或者为具有不变数据用于报告的MySQL服务器减少它。有关更多信息,请参见第14.4.2节“更改缓冲区”和
第14.6.5节“配置InnoDB更改缓冲区”。有关通用I / O优化建议,请参见
第8.5.8节“优化InnoDB磁盘I / O”。
| 属性 | 值 |
|---|---|
| 命令行格式 | --innodb-change-buffering=# |
| 系统变量 | innodb_change_buffering |
| 范围 | 全球 |
| 动态 | 是 |
| 类型 | 列举 |
| 默认 | all |
| 有效值 |
|
是否InnoDB执行
更改缓冲,优化将写操作延迟到二级索引,以便可以顺序执行I / O操作。下表描述了允许的值。
表14.13 innodb_change_buffering的允许值
| 值 | 描述 |
|---|---|
none |
不要缓冲任何操作。 |
inserts |
缓冲区插入操作。 |
deletes |
缓冲区删除标记操作; 严格来说,在清除操作期间标记索引记录以供稍后删除的写入。 |
changes |
缓冲区插入和删除标记操作。 |
purges |
缓冲在后台发生的物理删除操作。 |
all |
默认值。缓冲区插入,删除标记操作和清除。 |
有关更多信息,请参见 第14.4.2节“更改缓冲区”和 第14.6.5节“配置InnoDB更改缓冲区”。有关通用I / O优化建议,请参见 第8.5.8节“优化InnoDB磁盘I / O”。
| 属性 | 值 |
|---|---|
| 命令行格式 | --innodb-change-buffering-debug=# |
| 系统变量 | innodb_change_buffering_debug |
| 范围 | 全球 |
| 动态 | 是 |
| 类型 | 整数 |
| 默认 | 0 |
| 最大 | 2 |
设置InnoDB更改缓冲的调试标志。值为1将强制更改缓冲区的所有更改。值为2会导致合并时崩溃。默认值为0表示未设置更改缓冲调试标志。此选项仅在使用CMake选项编译调试支持时可用。
WITH_DEBUG
| 属性 | 值 |
|---|---|
| 命令行格式 | --innodb-checksum-algorithm=# |
| 系统变量 | innodb_checksum_algorithm |
| 范围 | 全球 |
| 动态 | 是 |
| 类型 | 列举 |
| 默认(> = 5.7.7) | crc32 |
| 默认(<= 5.7.6) | innodb |
| 有效值 |
|
指定如何生成和验证存储在表空间磁盘块中的
校验和。
是MySQL 5.7.7的默认值。
InnoDB
crc32
innodb_checksum_algorithm取代
innodb_checksums选项。为兼容性提供了以下值,直至并包括MySQL 5.7.6:
innodb_checksums=ON是一样的
innodb_checksum_algorithm=innodb。
innodb_checksums=OFF是一样的
innodb_checksum_algorithm=none。
从MySQL 5.7.7开始,默认innodb_checksum_algorithm值为crc32,
innodb_checksums=ON现在与之
相同
innodb_checksum_algorithm=crc32。
innodb_checksums=OFF仍然是一样的
innodb_checksum_algorithm=none。
为避免冲突,请删除对innodb_checksumsMySQL配置文件和启动脚本的引用
。
该值innodb与早期版本的MySQL向后兼容。该值
crc32使用更快的算法计算每个修改块的校验和,并检查每个磁盘读取的校验和。它每次扫描32位数据块,这比innodb
校验和算法更快,每次扫描8位数据块。该值none在校验和字段中写入常数值,而不是基于块数据计算值。表空间中的块可以混合使用旧的,新的和不需要的校验和值,随着数据的修改逐渐更新; 一旦表空间中的块被修改为使用crc32 算法,关联的表不能被早期版本的MySQL读取。
如果在表空间中遇到有效的但不匹配的校验和值,则校验和算法的严格形式会报告错误。建议您只在新实例中使用严格设置,以便第一次设置表空间。严格的设置速度会更快,因为它们不需要在磁盘读取期间计算所有校验和值。
在MySQL 5.7.8之前,严格模式设置会
innodb_checksum_algorithm导致
InnoDB在遇到有效但不匹配的校验和时停止
。在MySQL 5.7.8和更高版本中,只打印错误消息,并且如果页面具有有效的或
校验和innodb,则该页面被接受为有效
。
crc32none
下表显示了之间的区别
none,innodb和
crc32选项值,和他们同行的严格。none,
innodb并将crc32指定类型的校验和值写入每个数据块,但为了兼容性,在读取操作期间验证块时接受其他校验和值。严格设置也接受有效校验和值,但在遇到有效的不匹配校验和值时输出错误消息。如果InnoDB实例中的所有数据文件都以相同的innodb_checksum_algorithm值创建,
那么使用严格形式可以使验证更快
。
表14.14允许的innodb_checksum_algorithm值
| 值 | 生成的校验和(写入时) | 允许的校验和(阅读时) |
|---|---|---|
| 没有 | 一个常数。 | 任何校验的产生通过none,
innodb或crc32。 |
| InnoDB的 | 用软件计算校验和,使用原始算法
InnoDB。 |
任何校验的产生通过none,
innodb或crc32。 |
| CRC32 | 使用该crc32算法计算校验和,可能使用硬件辅助。 |
任何校验的产生通过none,
innodb或crc32。 |
| strict_none | 一个常数 | 任何校验的产生通过none,
innodb或crc32。
InnoDB如果遇到有效但不匹配的校验和,则输出错误消息。 |
| strict_innodb | 用软件计算校验和,使用原始算法
InnoDB。 |
任何校验的产生通过none,
innodb或crc32。
InnoDB如果遇到有效但不匹配的校验和,则输出错误消息。 |
| strict_crc32 | 使用该crc32算法计算校验和,可能使用硬件辅助。 |
任何校验的产生通过none,
innodb或crc32。
InnoDB如果遇到有效但不匹配的校验和,则输出错误消息。 |
MySQL Enterprise Backup 版本高达3.8.0不支持使用CRC32校验和的表空间备份。 MySQL Enterprise Backup在3.8.1中添加了CRC32校验和支持,但有一些限制。有关更多信息,请参阅 MySQL企业备份 3.8.1更改历史记录。
| 属性 | 值 |
|---|---|
| 命令行格式 | --innodb-checksums |
| 弃用 | 是 |
| 系统变量 | innodb_checksums |
| 范围 | 全球 |
| 动态 | 没有 |
| 类型 | 布尔 |
| 默认 | ON |
InnoDB可以对从磁盘读取的所有表空间页面使用
校验和验证,以确保对硬件故障或损坏的数据文件提供额外的容错能力。此验证默认启用。在特殊情况下(例如运行基准测试时),此安全功能可以被禁用
--skip-innodb-checksums。您可以指定使用该innodb_checksum_algorithm
选项计算校验和的方法
。
innodb_checksums已弃用,取而代之
innodb_checksum_algorithm。
在MySQL 5.7.7之前,和之前innodb_checksums=ON
一样
innodb_checksum_algorithm=innodb。从MySQL 5.7.7开始,innodb_checksum_algorithm
默认值是crc32,并且
与之
innodb_checksums=ON相同
innodb_checksum_algorithm=crc32。
innodb_checksums=OFF是一样的
innodb_checksum_algorithm=none。
innodb_checksums从配置文件和启动脚本中
删除任何选项以避免与之冲突innodb_checksum_algorithm。
innodb_checksums=OFF自动设置
innodb_checksum_algorithm=none。
innodb_checksums=ON被忽略并被任何其他设置覆盖
innodb_checksum_algorithm。
| 属性 | 值 |
|---|---|
| 命令行格式 | --innodb-cmp-per-index-enabled=# |
| 系统变量 | innodb_cmp_per_index_enabled |
| 范围 | 全球 |
| 动态 | 是 |
| 类型 | 布尔 |
| 默认 | OFF |
| 有效值 |
|
在INFORMATION_SCHEMA.INNODB_CMP_PER_INDEX
表中启用与索引压缩相关的统计信息
。由于这些统计信息收集起来可能很昂贵,因此只能在与InnoDB
压缩表相关的性能调整期间在开发,测试或从属实例上启用此选项
。
有关更多信息,请参见 第24.31.6节“INFORMATION_SCHEMA INNODB_CMP_PER_INDEX和INNODB_CMP_PER_INDEX_RESET表”以及 第14.9.1.4节“运行时监控InnoDB表压缩”。
| 属性 | 值 |
|---|---|
| 命令行格式 | --innodb-commit-concurrency=# |
| 系统变量 | innodb_commit_concurrency |
| 范围 | 全球 |
| 动态 | 是 |
| 类型 | 整数 |
| 默认 | 0 |
| 最低限度 | 0 |
| 最大 | 1000 |
可以同时提交 的线程数。值为0(默认值)允许同时提交任意数量的 事务。
innodb_commit_concurrency
在运行时间
的值不能从零变到非零,反之亦然。该值可以从一个非零值更改为另一个值。
| 属性 | 值 |
|---|---|
| 命令行格式 | --innodb-compress-debug=# |
| 介绍 | 5.7.8 |
| 系统变量 | innodb_compress_debug |
| 范围 | 全球 |
| 动态 | 是 |
| 类型 | 列举 |
| 默认 | none |
| 有效值 |
|
使用指定的压缩算法压缩所有表,而无需COMPRESSION
为每个表定义属性。该选项仅在使用CMake选项编译调试支持时可用
。
WITH_DEBUG
有关相关信息,请参见 第14.9.2节“InnoDB页面压缩”。
innodb_compression_failure_threshold_pct
| 属性 | 值 |
|---|---|
| 命令行格式 | --innodb-compression-failure-threshold-pct=# |
| 系统变量 | innodb_compression_failure_threshold_pct |
| 范围 | 全球 |
| 动态 | 是 |
| 类型 | 整数 |
| 默认 | 5 |
| 最低限度 | 0 |
| 最大 | 100 |
定义表格的压缩失败率阈值,以百分比表示,在这一点上,MySQL开始在压缩
页面中添加填充以避免昂贵的
压缩失败。当这个阈值通过时,MySQL开始在每个新的压缩页面中留下额外的可用空间,动态调整可用空间的数量直到由指定的页面大小的百分比
innodb_compression_pad_pct_max。值为零将禁用监视压缩效率并动态调整填充量的机制。
有关更多信息,请参见 第14.9.1.6节“针对OLTP工作负载的压缩”。
| 属性 | 值 |
|---|---|
| 命令行格式 | --innodb-compression-level=# |
| 系统变量 | innodb_compression_level |
| 范围 | 全球 |
| 动态 | 是 |
| 类型 | 整数 |
| 默认 | 6 |
| 最低限度 | 0 |
| 最大 | 9 |
指定用于InnoDB
压缩表和索引的zlib压缩级别
。较高的值可让您将更多数据放入存储设备,但压缩过程中CPU的开销会增加。当存储空间不重要时,较低的值可以减少CPU开销,或者您期望数据不是特别可压缩的。
有关更多信息,请参见 第14.9.1.6节“针对OLTP工作负载的压缩”。
innodb_compression_pad_pct_max
| 属性 | 值 |
|---|---|
| 命令行格式 | --innodb-compression-pad-pct-max=# |
| 系统变量 | innodb_compression_pad_pct_max |
| 范围 | 全球 |
| 动态 | 是 |
| 类型 | 整数 |
| 默认 | 50 |
| 最低限度 | 0 |
| 最大 | 75 |
指定每个压缩页内可保留为空闲空间的最大百分比,
当更新压缩表或索引并可重新压缩数据时,允许空间重新组织页面中的数据和修改日志。仅适用于
innodb_compression_failure_threshold_pct
设置为非零值时,压缩失败率
通过截断点。
有关更多信息,请参见 第14.9.1.6节“针对OLTP工作负载的压缩”。
| 属性 | 值 |
|---|---|
| 命令行格式 | --innodb-concurrency-tickets=# |
| 系统变量 | innodb_concurrency_tickets |
| 范围 | 全球 |
| 动态 | 是 |
| 类型 | 整数 |
| 默认 | 5000 |
| 最低限度 | 1 |
| 最大 | 4294967295 |
确定可以并发输入
的线程数
InnoDB。如果线程InnoDB数量已达到并发限制,则线程在尝试进入队列时放入队列。当一个线程被允许进入时
InnoDB,它被赋予与其值相等
的许多“
门票 ”innodb_concurrency_tickets,并且线程可以InnoDB
自由进入和离开,直到其用完门票。在那之后,线程在下次尝试进入时再次受到并发检查(以及可能的排队)的影响
InnoDB。默认值是5000。
如果innodb_concurrency_tickets
值很小,那么只需要处理几行的小事务就可以与处理许多行的较大事务公平竞争。小innodb_concurrency_tickets值的缺点
是大型事务必须在完成之前多次遍历队列,这会延长完成任务所需的时间。
具有较大的innodb_concurrency_tickets
值时,大型事务花费较少的时间来等待队列末尾的位置(由控制
innodb_thread_concurrency)并且更多时间检索行。大型交易还需要更少的队列来完成任务。较大的缺点
innodb_concurrency_tickets是,同时运行的大量事务可能会导致较小的事务处理,因此在执行前等待较长的时间。
使用非零
innodb_thread_concurrency
值时,您可能需要innodb_concurrency_tickets向上或向下调整该
值以在较大和较小交易之间找到最佳平衡点。该SHOW ENGINE INNODB STATUS
报告显示当前通过队列的执行事务的剩余票证数量。这些数据也可以从
表中的
TRX_CONCURRENCY_TICKETS列中获得
INFORMATION_SCHEMA.INNODB_TRX。
有关更多信息,请参见 第14.6.6节“为InnoDB配置线程并发”。
| 属性 | 值 |
|---|---|
| 命令行格式 | --innodb-data-file-path=name |
| 系统变量 | innodb_data_file_path |
| 范围 | 全球 |
| 动态 | 没有 |
| 类型 | 串 |
| 默认 | ibdata1:12M:autoextend |
定义InnoDB
系统表空间 数据文件的名称,大小和属性
。如果您未指定值
innodb_data_file_path,则默认行为是创建一个自动扩展数据文件,该文件略大于12MB,即已命名
ibdata1。
数据文件规范的完整语法包括文件名,文件大小autoextend和
max属性:
file_name:file_size[:autoextend [:max:max_file_size]]
文件大小通过追加指定KB,MB或GB(1024MB)
K,M或
G大小值。如果以千字节(KB)为单位指定数据文件大小,请以1024的倍数进行此操作。否则,将KB值四舍五入为最接近兆字节(MB)的边界。文件大小的总和必须至少略大于12MB。
为第一个系统表空间数据文件强制执行最小文件大小, 以确保有足够的空间存储双倍缓冲页面:
对于innodb_page_size
16KB或更小的值,最小文件大小为3MB。
对于innodb_page_size
32KB 的值,最小文件大小为6MB。
对于innodb_page_size
64KB 的值,最小文件大小为12MB。
单个文件的大小限制取决于您的操作系统。在支持大文件的操作系统上,您可以将文件大小设置为4GB以上。您还可以 使用原始磁盘分区作为数据文件。
该autoextend和max
属性只能用于将最后一个指定的数据文件中使用
innodb_data_file_path
的设置。例如:
的[mysqld] innodb_data_file_path中= ibdata1中:50M; ibdata2:12M:自动扩展:最大:500MB
如果您指定了该autoextend选项,那么
InnoDB扩展数据文件(如果它的空闲空间不足)。该autoextend增量是默认64MB。要修改增量,请更改
innodb_autoextend_increment
系统变量。
系统表空间数据文件的完整目录路径是通过连接由innodb_data_home_dir和
定义的路径形成的
innodb_data_file_path。
有关配置系统表空间数据文件的更多信息,请参见 第14.6.1节“InnoDB启动配置”。
| 属性 | 值 |
|---|---|
| 命令行格式 | --innodb-data-home-dir=dir_name |
| 系统变量 | innodb_data_home_dir |
| 范围 | 全球 |
| 动态 | 没有 |
| 类型 | 目录名称 |
InnoDB
系统表空间数据文件
的目录路径的公共部分
。此设置
在启用时不会影响每个表文件表空间
的位置
innodb_file_per_table。默认值是MySQL
data目录。如果您将该值指定为空字符串,则可以为其指定绝对文件路径
innodb_data_file_path。
指定值时需要尾部斜线
innodb_data_home_dir。例如:
的[mysqld] innodb_data_home_dir = / path / to / myibdata /
有关相关信息,请参见 第14.6.1节“InnoDB启动配置”。
| 属性 | 值 |
|---|---|
| 命令行格式 | --innodb-deadlock-detect |
| 介绍 | 5.7.15 |
| 系统变量 | innodb_deadlock_detect |
| 范围 | 全球 |
| 动态 | 是 |
| 类型 | 布尔 |
| 默认 | ON |
该选项用于禁用死锁检测。在高并发系统上,当大量线程等待相同的锁时,死锁检测会导致速度下降。有时候,innodb_lock_wait_timeout
当死锁发生时,禁用死锁检测并依赖事务回滚的设置可能更有效。
相关信息请参见 第14.5.5.2节“死锁检测和回滚”。
| 属性 | 值 |
|---|---|
| 命令行格式 | --innodb-default-row-format=# |
| 介绍 | 5.7.9 |
| 系统变量 | innodb_default_row_format |
| 范围 | 全球 |
| 动态 | 是 |
| 类型 | 列举 |
| 默认 | DYNAMIC |
| 有效值 |
|
该innodb_default_row_format选项定义InnoDB
表格和用户创建的临时表格的默认行格式。默认设置是DYNAMIC。其他允许的值是
COMPACT和REDUNDANT。COMPRESSED不支持在系统表空间中使用的行格式
不能被定义为默认值。
新创建的表格使用在未明确指定选项或使用选项innodb_default_row_format
时定义的行格式
。
ROW_FORMATROW_FORMAT=DEFAULT
如果ROW_FORMAT未明确指定选项或者何时ROW_FORMAT=DEFAULT使用选项,则重建表的任何操作也会静默地将表格的行格式更改为由其定义的格式
innodb_default_row_format。有关更多信息,请参见
第14.11.2节“指定表格的行格式”。
无论
设置如何,InnoDB由服务器创建的用于处理查询的
内部临时表都使用
DYNAMIC行格式
innodb_default_row_format。
innodb_disable_sort_file_cache
| 属性 | 值 |
|---|---|
| 命令行格式 | --innodb-disable-sort-file-cache=# |
| 系统变量 | innodb_disable_sort_file_cache |
| 范围 | 全球 |
| 动态 | 是 |
| 类型 | 布尔 |
| 默认 | OFF |
为合并分类临时文件禁用操作系统文件系统缓存。效果是打开这样的文件等价于O_DIRECT。
innodb_disable_resize_buffer_pool_debug
| 属性 | 值 |
|---|---|
| 命令行格式 | --innodb-disable-resize-buffer-pool-debug=# |
| 介绍 | 5.7.6 |
| 系统变量 | innodb_disable_resize_buffer_pool_debug |
| 范围 | 全球 |
| 动态 | 是 |
| 类型 | 布尔 |
| 默认 | ON |
禁用调整InnoDB缓冲池的大小。该选项仅在使用CMake选项编译调试支持时可用。
WITH_DEBUG
| 属性 | 值 |
|---|---|
| 命令行格式 | --innodb-doublewrite |
| 系统变量 | innodb_doublewrite |
| 范围 | 全球 |
| 动态 | 没有 |
| 类型 | 布尔 |
| 默认 | ON |
启用时(默认),InnoDB将所有数据存储两次,首先存储到
双写缓冲区,然后存入实际的
数据文件。--skip-innodb_doublewrite当需要最高性能而不是关心数据完整性或可能的故障时,可以关闭此变量以
用于基准或案例。
如果系统表空间数据文件(ibdata*
文件)位于支持原子写入的Fusion-io设备上,则会自动禁用双写缓冲,并将Fusion-io原子写入用于所有数据文件。由于双写缓冲区设置是全局性的,所以对于驻留在非Fusion-io硬件上的数据文件,也会禁用双写缓冲。此功能仅在Fusion-io硬件上受支持,并且仅在Linux上启用Fusion-io NVMFS。要充分利用此功能,建议使用此
innodb_flush_method设置O_DIRECT。
相关信息请参见 第14.4.7节“Doublewrite Buffer”。
| 属性 | 值 |
|---|---|
| 命令行格式 | --innodb-fast-shutdown[=#] |
| 系统变量 | innodb_fast_shutdown |
| 范围 | 全球 |
| 动态 | 是 |
| 类型 | 整数 |
| 默认 | 1 |
| 有效值 |
|
在InnoDB
关机模式。如果值为0,InnoDB则在关闭之前执行
缓慢关闭,全部清除和更改缓冲区合并。如果该值为1(默认值),则InnoDB在关闭时跳过这些操作,这个过程称为
快速关闭。如果该值为2,则InnoDB刷新其日志并关闭冷却,就好像MySQL崩溃了一样; 没有提交的事务丢失,但
崩溃恢复
操作使下一次启动需要更长的时间。
在大量数据仍然被缓冲的极端情况下,缓慢关机可能需要几分钟甚至几小时。在MySQL主要版本之间升级或降级之前,请使用慢速关闭技术,以便在升级过程更新文件格式时全部准备好所有数据文件。
使用innodb_fast_shutdown=2紧急或故障的情况下,获得绝对最快关机,如果数据是在损坏的风险。
innodb_fil_make_page_dirty_debug
| 属性 | 值 |
|---|---|
| 命令行格式 | --innodb-fil-make-page-dirty-debug=# |
| 系统变量 | innodb_fil_make_page_dirty_debug |
| 范围 | 全球 |
| 动态 | 是 |
| 类型 | 整数 |
| 默认 | 0 |
| 最大 | 2**32-1 |
默认情况下,设置
innodb_fil_make_page_dirty_debug为表空间的ID会立即污染表空间的第一页。如果
innodb_saved_page_number_debug
设置为非默认值,innodb_fil_make_page_dirty_debug请将指定页面设置为
灰色。该
innodb_fil_make_page_dirty_debug选项仅在使用CMake选项编译调试支持时可用
。
WITH_DEBUG
| 属性 | 值 |
|---|---|
| 命令行格式 | --innodb-file-format=# |
| 弃用 | 5.7.7 |
| 系统变量 | innodb_file_format |
| 范围 | 全球 |
| 动态 | 是 |
| 类型 | 串 |
| 默认(> = 5.7.7) | Barracuda |
| 默认(<= 5.7.6) | Antelope |
| 有效值 |
|
InnoDB为每个文件表格
空间
启用文件格式
。支持的文件格式是
Antelope和Barracuda。
Antelope是原始
InnoDB文件格式,支持
REDUNDANT和COMPACT
行格式。Barracuda是新的文件格式,支持COMPRESSED和
DYNAMIC行格式。
COMPRESSED和DYNAMIC
行格式为InnoDB表格提供重要的存储功能
。请参见
第14.11节“InnoDB行存储和行格式”。
更改
innodb_file_format设置不会影响现有InnoDB表空间文件的文件格式
。
该innodb_file_format
设置不适用于支持所有行格式表的常规表空间。请参见
14.7.9节,“InnoDB常规表空间”。
该innodb_file_format
默认值改为Barracuda在MySQL 5.7。
innodb_file_format
创建使用DYNAMIC行格式的表时,
该设置将被忽略
。无论设置如何,使用DYNAMIC行格式创建的表格始终使用
Barracuda文件格式
innodb_file_format。要使用COMPRESSED行格式,
innodb_file_format必须设置为Barracuda。
该innodb_file_format选项已被弃用,将在未来版本中删除。该innodb_file_format选项的目的
是允许用户降级到InnoDBMySQL 5.1中的内置版本
。现在MySQL 5.1已经到了其产品生命周期的最后阶段,这个选项提供的降级支持就不再需要了。
有关更多信息,请参见 第14.10节“InnoDB文件格式管理”。
| 属性 | 值 |
|---|---|
| 命令行格式 | --innodb-file-format-check=# |
| 弃用 | 5.7.7 |
| 系统变量 | innodb_file_format_check |
| 范围 | 全球 |
| 动态 | 没有 |
| 类型 | 布尔 |
| 默认 | ON |
在服务器启动时,可以将此变量设置为1或0,以启用或禁用是否InnoDB检查系统表空间中的
文件格式标记
(例如或
)。如果检查标签并且高于当前版本支持的标签
,则会发生错误并且
不会启动。如果标签不高,则将值设置
为文件格式标签。
AntelopeBarracudaInnoDBInnoDBInnoDBinnodb_file_format_max
尽管默认值有时显示为
ON或OFF,但始终使用数字值1或0在配置文件或命令行字符串中打开或关闭此选项。
有关更多信息,请参见 第14.10.2.1节“InnoDB启动时的兼容性检查”。
该innodb_file_format_check
选项与innodb_file_format选项一起被弃用
。这两个选项将在未来版本中删除。
| 属性 | 值 |
|---|---|
| 命令行格式 | --innodb-file-format-max=# |
| 弃用 | 5.7.7 |
| 系统变量 | innodb_file_format_max |
| 范围 | 全球 |
| 动态 | 是 |
| 类型 | 串 |
| 默认(> = 5.7.9) | Barracuda |
| 默认(<= 5.7.8) | Antelope |
| 有效值 |
|
在服务器启动时,InnoDB将此变量的值设置为系统表空间中的文件格式标记
(例如或
)。如果服务器创建或打开具有“ 更高 ”文件格式的表格,则将该值设置
为该格式。
AntelopeBarracudainnodb_file_format_max
有关相关信息,请参见 第14.10节“InnoDB文件格式管理”。
该innodb_file_format_max
选项与innodb_file_format选项一起被弃用
。这两个选项将在未来版本中删除。
| 属性 | 值 |
|---|---|
| 命令行格式 | --innodb-file-per-table |
| 系统变量 | innodb_file_per_table |
| 范围 | 全球 |
| 动态 | 是 |
| 类型 | 布尔 |
| 默认 | ON |
当innodb_file_per_table启用(默认),InnoDB存储数据和索引在一个单独的每个新创建的表
.ibd
文件,而不是系统表空间。当这些表被删除或截断时,这些表的存储将被回收。此设置启用
InnoDB表格压缩等功能
。有关更多信息,请参见
第14.7.4节“InnoDB文件每表表空间”。
启用
innodb_file_per_table也意味着
在
重建table()的情况下,ALTER TABLE
操作会将InnoDB表从系统表空间移动到单个.ibd文件。此规则的一个例外是使用with 或
with选项
放置在系统表空间中的表
。这些表不受
设置的影响,只能移动到每个文件表的表空间。
ALTER TABLEALGORITHM=COPYTABLESPACE=innodb_systemCREATE TABLEALTER TABLEinnodb_file_per_tableALTER TABLE
... TABLESPACE=innodb_file_per_table
当innodb_file_per_table被禁用时,
InnoDB存储在表和索引数据ibdata文件组成的
系统表空间。此设置可降低诸如DROP TABLEor之
类操作的文件系统操作的性能开销
TRUNCATE TABLE。对于整个存储设备专用于MySQL数据的服务器环境来说,这是最合适的。由于系统表空间永远不会缩小,并且在实例中的所有数据库之间共享,因此避免在空间受限系统上加载大量临时数据innodb_file_per_table被禁用。在这种情况下设置一个单独的实例,以便您可以删除整个实例来回收空间。
innodb_file_per_table是默认启用的。如果与MySQL 5.5或5.1的向后兼容性值得关注,请考虑禁用它。这将防止
ALTER TABLE将InnoDB表从系统表空间移动
到单个.ibd文件。
innodb_file_per_table是动态的,可以设置ON或
OFF使用SET GLOBAL。您也可以在MySQL 配置文件(my.cnf或
my.ini)中设置此选项,
但这需要关闭并重新启动服务器。
动态更改该值需要
SUPER特权并立即影响所有连接的操作。
| 属性 | 值 |
|---|---|
| 命令行格式 | --innodb-fill-factor=# |
| 介绍 | 5.7.5 |
| 系统变量 | innodb_fill_factor |
| 范围 | 全球 |
| 动态 | 是 |
| 类型 | 整数 |
| 默认 | 100 |
| 最低限度 | 10 |
| 最大 | 100 |
InnoDB在创建或重建索引时执行批量加载。这种索引创建方法被称为“ 排序索引构建 ”。
innodb_fill_factor定义在排序索引构建期间填充的每个B树页面上的空间的百分比,其余空间保留用于未来的索引增长。例如,设置
innodb_fill_factor为80将保留每个B-tree页面上20%的空间用于未来的指数增长。实际百分比可能有所不同。该
innodb_fill_factor设置被解释为提示而不是硬限制。
一个innodb_fill_factor100设置叶免费为未来指数增长的聚簇索引页的空间的1/16。
innodb_fill_factor适用于B树叶和非叶页。它不适用于用于TEXT或
BLOB输入的外部页面。
有关更多信息,请参见 第14.8.2.3节“分类索引构建”。
| 属性 | 值 |
|---|---|
| 系统变量 | innodb_flush_log_at_timeout |
| 范围 | 全球 |
| 动态 | 是 |
| 类型 | 整数 |
| 默认 | 1 |
| 最低限度 | 1 |
| 最大 | 2700 |
每秒写入并刷新日志N
。
innodb_flush_log_at_timeout
允许增加刷新之间的超时时间以减少刷新并避免影响二进制日志组落实的性能。默认设置为
innodb_flush_log_at_timeout
每秒一次。
innodb_flush_log_at_trx_commit
| 属性 | 值 |
|---|---|
| 命令行格式 | --innodb-flush-log-at-trx-commit[=#] |
| 系统变量 | innodb_flush_log_at_trx_commit |
| 范围 | 全球 |
| 动态 | 是 |
| 类型 | 列举 |
| 默认 | 1 |
| 有效值 |
|
控制提交操作的严格ACID合规性与 提交相关I / O操作重新排列并批量完成时可能实现的更高性能之间的平衡 。您可以通过更改默认值来获得更好的性能,但在崩溃时您可能会丢失多达一秒的事务。
完全符合ACID要求默认值1。使用此值,InnoDB
日志缓冲区的内容会
在每次事务提交时写入日志文件,并将日志文件
刷新到磁盘。
值为0时,InnoDB日志缓冲区的内容
大约每秒写入日志文件一次,并将日志文件刷新到磁盘。事务提交时不执行从日志缓冲区到日志文件的写入操作。由于进程调度问题,每秒一次的刷新不能保证每秒发生一次。由于刷新到磁盘的操作大约每秒发生一次,因此任何mysqld进程崩溃都可能会丢失多达一秒的事务
。
值为2时,InnoDB日志缓冲区的内容
会在每次事务提交后写入日志文件,并且日志文件每秒大约刷新一次到磁盘。由于进程调度问题,每秒一次的冲洗并不是100%保证每秒发生。由于刷新到磁盘的操作只能每秒发生一次,因此在操作系统崩溃或停电时,可能会丢失多达一秒的事务。
InnoDB日志刷新频率由控制
innodb_flush_log_at_timeout,它允许用户设置记录冲洗频率以
N秒(其中
N是1 ...
2700,为1的默认值)。但是,任何
mysqld进程崩溃最多可以消除
N几秒钟的事务。
独立于设置的
DDL更改和其他内部InnoDB
活动刷新InnoDB日志
innodb_flush_log_at_trx_commit。
InnoDB
无论innodb_flush_log_at_trx_commit设置如何,崩溃恢复都可以工作
事务既可以完全应用,也可以完全擦除。
对于InnoDB与事务一起使用的复制设置中的耐久性和一致性:
如果启用二进制日志记录,则设置
sync_binlog=1。
始终设置
innodb_flush_log_at_trx_commit=1。
许多操作系统和一些磁盘硬件欺骗了磁盘到磁盘的操作。他们可能会告诉
mysqld已经发生刷新,尽管没有刷新。在这种情况下,即使使用设置1,交易的持久性也不能保证,并且在最坏的情况下,停电可能会破坏
InnoDB数据。在SCSI磁盘控制器或磁盘本身中使用电池供电的磁盘缓存可加速文件刷新,并使操作更安全。您还可以尝试禁用硬件缓存中的磁盘写入缓存。
| 属性 | 值 |
|---|---|
| 命令行格式 | --innodb-flush-method=name |
| 系统变量 | innodb_flush_method |
| 范围 | 全球 |
| 动态 | 没有 |
| 类型(Windows) | 串 |
| 类型(Unix) | 串 |
| 默认(Windows) | NULL |
| 默认(Unix) | NULL |
| 有效值(Windows) |
|
| 有效值(Unix) |
|
定义用于将
数据刷新到
InnoDB 数据文件和日志文件的方法,这会影响I / O吞吐量。
如果innodb_flush_method设置为
NULL在类Unix系统上,则fsync默认使用该
选项。如果
在Windows上innodb_flush_method设置为
NULL,则async_unbuffered默认使用该
选项。
innodb_flush_method类Unix系统
的选项包括:
fsync:InnoDB使用fsync()系统调用来刷新数据和日志文件。fsync是默认设置。
O_DSYNC:InnoDB用于
O_SYNC打开和刷新日志文件,并fsync()刷新数据文件。
InnoDB不O_DSYNC直接使用
,因为它在许多种类的Unix上都存在问题。
littlesync:此选项用于内部性能测试,目前不受支持。使用风险自负。
nosync:此选项用于内部性能测试,目前不受支持。使用风险自负。
O_DIRECT:InnoDB
使用O_DIRECT(或
directio()在Solaris上)打开数据文件,并使用它fsync()来刷新数据和日志文件。该选项在一些GNU / Linux版本,FreeBSD和Solaris上可用。
O_DIRECT_NO_FSYNC:
在刷新I / O期间InnoDB使用O_DIRECT,但在fsync()之后跳过
系统调用。此设置适用于某些类型的文件系统,但不适用于其他文件系统。例如,它不适用于XFS。如果您不确定您使用的文件系统是否需要某个文件系统
fsync(),例如保留所有文件元数据,请O_DIRECT改为使用。
innodb_flush_methodWindows系统
的选项包括:
async_unbuffered:
InnoDB使用Windows异步I / O和非缓冲I / O。async_unbuffered
是Windows系统上的默认设置。
在Windows上的4K扇区硬盘驱动器上运行MySQL服务器不支持async_unbuffered。解决方法是使用
innodb_flush_method=normal。
normal:InnoDB使用模拟异步I / O和缓冲I / O。
unbuffered:InnoDB
使用模拟异步I / O和非缓冲I / O。
每个设置如何影响性能取决于硬件配置和工作负载。对特定配置进行基准测试,以确定要使用的设置,还是保持默认设置。检查
Innodb_data_fsyncs状态变量以查看fsync()每个设置的总体呼叫数量
。工作负载中的读写操作可能会影响设置的执行方式。例如,在具有硬件RAID控制器和电池备份写缓存的系统上,
O_DIRECT可以帮助避免InnoDB缓冲池与操作系统文件系统缓存之间的双重缓冲。在某些系统上
InnoDB数据和日志文件位于SAN上,这是默认值,或者O_DSYNC对于大多数SELECT语句而言,读取繁重的工作负载可能会更快
。始终使用反映您生产环境的硬件和工作负载来测试此参数。有关通用I / O优化建议,请参见
第8.5.8节“优化InnoDB磁盘I / O”。
| 属性 | 值 |
|---|---|
| 命令行格式 | --innodb-flush-neighbors |
| 系统变量 | innodb_flush_neighbors |
| 范围 | 全球 |
| 动态 | 是 |
| 类型 | 列举 |
| 默认 | 1 |
| 有效值 |
|
指定是否冲洗从一个页面InnoDB
缓冲池也可以清空其他脏页在相同的
程度。
默认值1将从缓冲池中清除相同范围内的连续脏页。
设置为0将
innodb_flush_neighbors关闭,并且不会从缓冲池中清除其他脏页。
设置为2会从缓冲池中以相同范围刷新脏页。
当表格数据存储在传统的 HDD存储设备上时, 与在不同时间冲刷单独页面相比,在一个操作中刷新这样的相邻页面减少了I / O开销(主要用于磁盘搜索操作)。对于存储在SSD上的表格数据 ,查找时间不是一个重要因素,您可以关闭此设置以分散写入操作。有关相关信息,请参见 第14.6.3.7节“微调InnoDB缓冲池刷新”。
| 属性 | 值 |
|---|---|
| 命令行格式 | --innodb-flush-sync=# |
| 介绍 | 5.7.8 |
| 系统变量 | innodb_flush_sync |
| 范围 | 全球 |
| 动态 | 是 |
| 类型 | 布尔 |
| 默认 | ON |
该innodb_flush_sync参数默认情况下处于启用状态,导致
innodb_io_capacity设置在检查点发生的I / O活动突发中被忽略
。要遵守设置InnoDB定义的后台I / O活动
限制innodb_io_capacity,请禁用innodb_flush_sync。
有关相关信息,请参见 第14.6.9节“配置InnoDB主线程I / O速率”。
| 属性 | 值 |
|---|---|
| 命令行格式 | --innodb-flushing-avg-loops=# |
| 系统变量 | innodb_flushing_avg_loops |
| 范围 | 全球 |
| 动态 | 是 |
| 类型 | 整数 |
| 默认 | 30 |
| 最低限度 | 1 |
| 最大 | 1000 |
迭代次数InnoDB保持之前计算的刷新状态快照,控制
自适应刷新响应变化
工作负载的速度。随着工作负载的变化,增加值会使冲洗操作的速度
平稳且逐渐变化。降低该值会使自适应冲洗快速适应工作负载的变化,如果工作负载突然增加或减少,可能会导致冲刷活动出现峰值。
有关相关信息,请参见 第14.6.3.7节“微调InnoDB缓冲池刷新”。
| 属性 | 值 |
|---|---|
| 命令行格式 | --innodb-force-load-corrupted |
| 系统变量 | innodb_force_load_corrupted |
| 范围 | 全球 |
| 动态 | 没有 |
| 类型 | 布尔 |
| 默认 | OFF |
允许InnoDB在启动时加载标记为已损坏的表。仅在故障排除期间使用,以恢复无法访问的数据。故障排除完成后,请禁用此设置并重新启动服务器。
| 属性 | 值 |
|---|---|
| 命令行格式 | --innodb-force-recovery=# |
| 系统变量 | innodb_force_recovery |
| 范围 | 全球 |
| 动态 | 没有 |
| 类型 | 整数 |
| 默认 | 0 |
| 最低限度 | 0 |
| 最大 | 6 |
在崩溃恢复
模式,通常只有在认真排除故障的情况下更改。可能的值为0到6.有关这些值的含义和重要信息
innodb_force_recovery,请参见
第14.21.2节“强制InnoDB恢复”。
在紧急情况下,只能将此变量设置为大于0的值,以便您可以启动
InnoDB并转储您的表。作为安全措施,当大于0 时InnoDB防止
INSERT,
UPDATE或者
DELETE操作
innodb_force_recovery。innodb_force_recovery设置为4或更大的位置InnoDB进入只读模式。
这些限制可能会导致复制管理命令失败并显示错误,如复制选项(如
表--relay-log-info-repository=TABLE
和
--master-info-repository=TABLE
将信息存储在InnoDB表中)。
| 属性 | 值 |
|---|---|
| 命令行格式 | --innodb-ft-aux-table=# (> = 5.7.2) |
| 系统变量 | innodb_ft_aux_table |
| 范围 | 全球 |
| 动态 | 是 |
| 类型 | 串 |
指定InnoDB
包含FULLTEXT索引的表的限定名称。该变量用于诊断目的。
当您在格式这个变量设置为名称
的表格
,
,
,
,和
显示有关指定表的搜索索引信息。
db_name/table_nameINFORMATION_SCHEMAINNODB_FT_INDEX_TABLEINNODB_FT_INDEX_CACHEINNODB_FT_CONFIGINNODB_FT_DELETEDINNODB_FT_BEING_DELETED
有关更多信息,请参见 第14.15.4节“InnoDB INFORMATION_SCHEMA全文索引表”。
| 属性 | 值 |
|---|---|
| 命令行格式 | --innodb-ft-cache-size=# |
| 系统变量 | innodb_ft_cache_size |
| 范围 | 全球 |
| 动态 | 没有 |
| 类型 | 整数 |
| 默认 | 8000000 |
| 最低限度 | 1600000 |
| 最大 | 80000000 |
以字节为单位分配的内存用于
InnoDB FULLTEXT搜索索引缓存,该缓存在创建InnoDB
FULLTEXT索引时在内存中保存已分析的文档。索引插入和更新仅在innodb_ft_cache_size达到大小限制时才提交给磁盘
。
innodb_ft_cache_size以每个表为基础定义高速缓存大小。要为所有表设置全局限制,请参阅
innodb_ft_total_cache_size。
有关更多信息,请参阅 InnoDB全文索引缓存。
| 属性 | 值 |
|---|---|
| 命令行格式 | --innodb-ft-enable-diag-print=# |
| 系统变量 | innodb_ft_enable_diag_print |
| 范围 | 全球 |
| 动态 | 是 |
| 类型 | 布尔 |
| 默认 | OFF |
是否启用附加的全文搜索(FTS)诊断输出。此选项主要用于高级FTS调试,对大多数用户不感兴趣。输出打印到错误日志中,并包含以下信息:
FTS索引同步进度(达到FTS高速缓存限制时)。例如:
用于表测试的FTS SYNC,删除的计数:100大小:10000字节 同步字:100
FTS优化进展。例如:
FTS开始优化测试 FTS_OPTIMIZE:优化“mysql” FTS_OPTIMIZE:处理“mysql”
FTS指数建立进度。例如:
处理的文档数量:1000
对于FTS查询,将打印查询解析树,文字权重,查询处理时间和内存使用情况。例如:
FTS搜索处理时间:1秒:100毫秒:行10000 全搜索内存:245666(字节),行:10000
| 属性 | 值 |
|---|---|
| 命令行格式 | --innodb-ft-enable-stopword=# |
| 系统变量 | innodb_ft_enable_stopword |
| 范围 | 全球 |
| 动态 | 是 |
| 类型 | 布尔 |
| 默认 | ON |
指定
在索引创建时一组
停用词与InnoDB FULLTEXT索引关联。如果该
innodb_ft_user_stopword_table
选项已设置,则停用词将从该表中获取。否则,如果
innodb_ft_server_stopword_table
选项已设置,则停用词将从该表中提取。否则,使用内置的一组默认停用词。
有关更多信息,请参见 第12.9.4节“全文停用词”。
| 属性 | 值 |
|---|---|
| 命令行格式 | --innodb-ft-max-token-size=# |
| 系统变量 | innodb_ft_max_token_size |
| 范围 | 全球 |
| 动态 | 没有 |
| 类型 | 整数 |
| 类型 | 整数 |
| 默认 | 84 |
| 默认 | 84 |
| 最低限度 | 10 |
| 最低限度 | 10 |
| 最大(> = 5.7.3) | 84 |
| 最大(<= 5.7.2) | 252 |
| 最大 | 84 |
存储在InnoDB FULLTEXT索引中的单词的最大字符长度
。对此值设置限制可以减小索引的大小,从而加快查询速度,方法是省略长关键字或任意字母集合,这些字母不是真正的单词,也不可能是搜索术语。
有关更多信息,请参见 第12.9.6节“微调MySQL全文搜索”。
| 属性 | 值 |
|---|---|
| 命令行格式 | --innodb-ft-min-token-size=# |
| 系统变量 | innodb_ft_min_token_size |
| 范围 | 全球 |
| 动态 | 没有 |
| 类型 | 整数 |
| 默认 | 3 |
| 最低限度 | 0 |
| 最大 | 16 |
存储在InnoDB FULLTEXT索引中的单词的最小长度
。增加此值可减小索引的大小,从而通过省略在搜索上下文中不太可能显着的常见单词(如英语单词“ a ”和“ to ”)来加快查询速度。对于使用CJK(中文,日文,韩文)字符集的内容,请指定值1。
有关更多信息,请参见 第12.9.6节“微调MySQL全文搜索”。
| 属性 | 值 |
|---|---|
| 命令行格式 | --innodb-ft-num-word-optimize=# |
| 系统变量 | innodb_ft_num_word_optimize |
| 范围 | 全球 |
| 动态 | 是 |
| 类型 | 整数 |
| 默认 | 2000 |
索引OPTIMIZE TABLE上
每次操作
期间要处理的字数
InnoDB FULLTEXT。由于对包含全文搜索索引的表进行大容量插入或更新操作可能需要大量索引维护才能包含所有更改,因此您可能会执行一系列OPTIMIZE TABLE
语句,每个语句都会从最后一次离开的位置开始。
有关更多信息,请参见 第12.9.6节“微调MySQL全文搜索”。
| 属性 | 值 |
|---|---|
| 命令行格式 | --innodb-ft-result-cache-limit=# |
| 介绍 | 5.7.2 |
| 系统变量 | innodb_ft_result_cache_limit |
| 范围 | 全球 |
| 动态 | 是 |
| 类型(Windows,> = 5.7.2,<= 5.7.3) | 整数 |
| 类型(Unix,64位平台,> = 5.7.2,<= 5.7.3) | 整数 |
| 类型(Unix,32位平台,> = 5.7.2,<= 5.7.3) | 整数 |
| 类型(> = 5.7.4) | 整数 |
| 默认值(Windows,> = 5.7.2,<= 5.7.3) | 2000000000 |
| 缺省值(Unix,64位平台,> = 5.7.2,<= 5.7.3) | 2000000000 |
| 缺省值(Unix,32位平台,> = 5.7.2,<= 5.7.3) | 2000000000 |
| 默认(> = 5.7.4) | 2000000000 |
| 最小值(Windows,> = 5.7.2,<= 5.7.3) | 1000000 |
| 最小(Unix,64位平台,> = 5.7.2,<= 5.7.3) | 1000000 |
| 最小(Unix,32位平台,> = 5.7.2,<= 5.7.3) | 1000000 |
| 最小(> = 5.7.4) | 1000000 |
| 最大值(Windows,> = 5.7.2,<= 5.7.3) | 2**32-1 |
| 最大(Unix,64位平台,> = 5.7.2,<= 5.7.3) | 2**64-1 |
| 最大(Unix,32位平台,> = 5.7.2,<= 5.7.3) | 2**32-1 |
| 最大(> = 5.7.4) | 2**32-1 |
在InnoDB每全文搜索查询或每个线程全文搜索查询结果高速缓存限制(以字节为单位定义)。InnoDB
在内存中处理中间和最终的全文搜索查询结果。用于
innodb_ft_result_cache_limit在全文搜索查询结果缓存中放置大小限制,以避免在非常大InnoDB的全文搜索查询结果(例如数百万或数亿行)情况下耗用过多的内存
。在处理全文搜索查询时,会根据需要分配内存。如果达到了结果缓存大小限制,则会返回错误,指示查询超出了允许的最大内存。
innodb_ft_result_cache_limit所有平台类型和位大小
的最大值
是2 ** 32-1。
innodb_ft_server_stopword_table
| 属性 | 值 |
|---|---|
| 命令行格式 | --innodb-ft-server-stopword-table=db_name/table_name |
| 系统变量 | innodb_ft_server_stopword_table |
| 范围 | 全球 |
| 动态 | 是 |
| 类型 | 串 |
| 默认 | NULL |
该选项用于InnoDB FULLTEXT为所有InnoDB表指定您自己的
索引停用词列表。要为特定InnoDB表配置您自己的停用词列表
,请使用
innodb_ft_user_stopword_table。
设置innodb_ft_server_stopword_table为包含停用词列表的表格名称,格式为
。
db_name/table_name
在配置之前,停用词表必须存在
innodb_ft_server_stopword_table。
innodb_ft_enable_stopword必须启用并且innodb_ft_server_stopword_table必须配置选项才能创建
FULLTEXT索引。
停用词表必须是InnoDB包含VARCHAR名为的单个列
的表value。
有关更多信息,请参见 第12.9.4节“全文停用词”。
| 属性 | 值 |
|---|---|
| 命令行格式 | --innodb-ft-sort-pll-degree=# |
| 系统变量 | innodb_ft_sort_pll_degree |
| 范围 | 全球 |
| 动态 | 没有 |
| 类型 | 整数 |
| 默认 | 2 |
| 最低限度 | 1 |
| 最大 | 32 |
InnoDB FULLTEXT
在构建搜索索引时
用于并行索引和标记索引中文本的线程数。
有关相关信息,请参见
第14.8.2.4节“InnoDB FULLTEXT索引”和
innodb_sort_buffer_size。
| 属性 | 值 |
|---|---|
| 命令行格式 | --innodb-ft-total-cache-size=# |
| 介绍 | 5.7.2 |
| 系统变量 | innodb_ft_total_cache_size |
| 范围 | 全球 |
| 动态 | 没有 |
| 类型 | 整数 |
| 默认 | 640000000 |
| 最低限度 | 32000000 |
| 最大 | 1600000000 |
InnoDB所有表格的全文搜索索引缓存
的总内存(以字节为单位)
。创建大量表格,每个表格都有一个
FULLTEXT搜索索引,可能会消耗大部分可用内存。
innodb_ft_total_cache_size
为所有全文搜索索引定义全局内存限制,以帮助避免过多的内存消耗。如果通过索引操作达到全局限制,则触发强制同步。
有关更多信息,请参阅 InnoDB全文索引缓存。
| 属性 | 值 |
|---|---|
| 命令行格式 | --innodb-ft-user-stopword-table=db_name/table_name |
| 系统变量 | innodb_ft_user_stopword_table |
| 范围 | 全球,会议 |
| 动态 | 是 |
| 类型 | 串 |
| 默认 | NULL |
该选项用于InnoDB FULLTEXT在特定表格上指定您自己的
索引停用词列表。要为所有InnoDB表配置您自己的停用词列表,请使用
innodb_ft_server_stopword_table。
设置innodb_ft_user_stopword_table为包含停用词列表的表格名称,格式为
。
db_name/table_name
在配置之前,停用词表必须存在
innodb_ft_user_stopword_table。
innodb_ft_enable_stopword必须启用并且innodb_ft_user_stopword_table必须在创建FULLTEXT
索引之前进行配置。
停用词表必须是InnoDB包含VARCHAR名为的单个列
的表value。
有关更多信息,请参见 第12.9.4节“全文停用词”。
| 属性 | 值 |
|---|---|
| 命令行格式 | --innodb-io-capacity=# |
| 系统变量 | innodb_io_capacity |
| 范围 | 全球 |
| 动态 | 是 |
| 类型(64位平台) | 整数 |
| 类型(32位平台) | 整数 |
| 默认(64位平台) | 200 |
| 默认(32位平台) | 200 |
| 最低(64位平台) | 100 |
| 最低(32位平台) | 100 |
| 最大(64位平台) | 2**64-1 |
| 最大(32位平台) | 2**32-1 |
该innodb_io_capacity
参数设置InnoDB后台任务每秒执行的I / O操作数的上限,例如刷新缓冲池中的
页面以及合并来自更改缓冲区的数据
。
该innodb_io_capacity限制是所有缓冲池实例的总限制。当刷新脏页时,限制在缓冲池实例中平均分配。
innodb_io_capacity应设置为大约系统每秒可执行的I / O操作数。理想情况下,保持尽可能低的设置,但不要太低以至于背景活动落后。如果该值太高,则数据将从缓冲池中删除,并且插入缓冲区太快而无法进行缓存以提供显着的优势。
缺省值为200.对于能够提高I / O速率的繁忙系统,可以设置较高的值以帮助服务器处理与高速行更改相关的后台维护工作。
通常,可以根据用于InnoDB
I / O 的驱动器数量增加该值。例如,您可以增加使用多个磁盘或固态磁盘(SSD)的系统上的值。
对于较低端的SSD,默认设置为200通常就足够了。例如,对于更高端的总线连接的SSD,考虑更高的设置,例如1000。对于具有单个5400 RPM或7200 RPM驱动器的系统,您可能会将该值降低到100,这代表可以执行大约100 IOPS的旧一代磁盘驱动器可用的每秒I / O操作(IOPS)的估计比例。
尽管您可以指定一个非常高的值,例如100万,但实际上,这样大的值几乎没有好处。通常,建议不要使用20000或更高的值,除非您已经证明较低的值不足以满足您的工作负载。
调整时考虑写入工作量
innodb_io_capacity。大写入工作负载的系统很可能从更高的设置中受益。对于写入工作量小的系统,较低的设置可能就足够了。
您可以将innodb_io_capacity任何数字设置为100或更大,以达到由其定义的最大值
innodb_io_capacity_max。
innodb_io_capacity可以在MySQL选项文件(my.cnf或
my.ini)中设置,也可以使用SET GLOBAL需要SUPER特权的语句
动态更改
。
的innodb_flush_sync
配置选项使
innodb_io_capacity发生在检查点I / O活动的脉冲串期间被忽略设置。
innodb_flush_sync是默认启用的。
有关更多信息,请参见第14.6.9节“配置InnoDB主线程I / O速率”。有关InnoDBI / O性能的一般信息
,请参见
第8.5.8节“优化InnoDB磁盘I / O”。
| 属性 | 值 |
|---|---|
| 命令行格式 | --innodb-io-capacity-max=# |
| 系统变量 | innodb_io_capacity_max |
| 范围 | 全球 |
| 动态 | 是 |
| 类型(Windows,64位平台) | 整数 |
| 类型(Unix,64位平台) | 整数 |
| 类型(32位平台) | 整数 |
| 默认(Windows,64位平台) | see description |
| 默认(Unix,64位平台) | see description |
| 默认(32位平台) | see description |
| 最低(Windows,64位平台) | 100 |
| 最低(Unix,64位平台) | 100 |
| 最低(32位平台) | 100 |
| 最大(Windows,64位平台) | 2**32-1 |
| 最大(Unix,64位平台) | 2**64-1 |
| 最大(32位平台) | 2**32-1 |
如果冲洗活动落后,InnoDB
可以冲洗的积极性超过了限制
innodb_io_capacity。
innodb_io_capacity_max定义了InnoDB在这种情况下背景任务每秒执行的I / O操作的数量的上限
。
该innodb_io_capacity_max
设置是所有缓冲池实例的总限制。
如果您innodb_io_capacity在启动时指定
设置,但不指定值for
innodb_io_capacity_max,则
innodb_io_capacity_max默认为值的两倍
innodb_io_capacity,最小值为2000。
配置时innodb_io_capacity_max,两倍innodb_io_capacity
通常是一个很好的起点。默认值2000适用于使用固态磁盘(SSD)或多个常规磁盘驱动器的工作负载。对于不使用SSD或多个磁盘驱动器的工作负载,2000的设置可能过高,并且可能会导致过多的刷新。对于单个普通磁盘驱动器,建议在200到400之间设置。对于高端,总线连接的SSD,考虑更高的设置,如2500.与
innodb_io_capacity设置一样,尽可能降低设置,但不要太低,以至于如果必要的话,
InnoDB不能超出innodb_io_capacity极限。
调整时考虑写入工作量
innodb_io_capacity_max。大写入工作负载的系统可能受益于更高的设置。对于写入工作量小的系统,较低的设置可能就足够了。
innodb_io_capacity_max不能设置为低于该
innodb_io_capacity值的值。
设置
innodb_io_capacity_max为
DEFAULT使用
SET
语句(SET GLOBAL
innodb_io_capacity_max=DEFAULT)设置
innodb_io_capacity_max为最大值。
有关相关信息,请参见 第14.6.3.7节“微调InnoDB缓冲池刷新”。
| 属性 | 值 |
|---|---|
| 命令行格式 | --innodb-large-prefix |
| 弃用 | 5.7.7 |
| 系统变量 | innodb_large_prefix |
| 范围 | 全球 |
| 动态 | 是 |
| 类型 | 布尔 |
| 默认(> = 5.7.7) | ON |
| 默认(<= 5.7.6) | OFF |
启用此选项时,对于InnoDB使用DYNAMIC
或
COMPRESSED
行格式的表,允许使用
长度超过767个字节(最多3072个字节)的索引键前缀
。请参阅第14.8.1.7节“InnoDB表的限制”,了解与各种设置下的索引键前缀相关的最大值。
对于使用REDUNDANT
或
COMPACT
行格式的表
,此选项不会影响允许的索引键前缀长度。
innodb_large_prefix在MySQL 5.7中默认启用。此更改与MySQL 5.7中默认innodb_file_format设置
的默认值更改一致
Barracuda。总之,这些默认值更改允许在使用DYNAMIC或COMPRESSED
行格式时创建更大的索引键前缀
。如果任一选项设置为非默认值,则会自动截断大于767字节的索引键前缀。
innodb_large_prefix已弃用,将在未来版本中删除。
innodb_large_prefix在MySQL 5.5中引入,以禁用大型索引键前缀,以便与InnoDB不支持大型索引键前缀的早期版本兼容
。
innodb_limit_optimistic_insert_debug
| 属性 | 值 |
|---|---|
| 命令行格式 | --innodb-limit-optimistic-insert-debug=# |
| 系统变量 | innodb_limit_optimistic_insert_debug |
| 范围 | 全球 |
| 动态 | 是 |
| 类型 | 整数 |
| 默认 | 0 |
| 最低限度 | 0 |
| 最大 | 2**32-1 |
限制每个B-Tree页面的记录数量
。默认值0意味着没有限制。该选项仅在使用CMake选项编译调试支持时可用
。
WITH_DEBUG
| 属性 | 值 |
|---|---|
| 命令行格式 | --innodb-lock-wait-timeout=# |
| 系统变量 | innodb_lock_wait_timeout |
| 范围 | 全球,会议 |
| 动态 | 是 |
| 类型 | 整数 |
| 默认 | 50 |
| 最低限度 | 1 |
| 最大 | 1073741824 |
在放弃之前InnoDB
事务等待行锁
的时间长度(以秒为单位)。默认值是50秒。尝试访问由另一个InnoDB事务锁定的行的
事务在发出以下错误之前至多等待对该行的写访问权限:
错误1205(HY000):超出锁定等待超时; 尝试重新启动事务
当发生锁定等待超时时,当前语句被
回滚(而不是整个事务)。要使整个事务回滚,请使用该--innodb_rollback_on_timeout
选项启动服务器
。另请参见第14.21.4节“InnoDB错误处理”。
对于高度交互式应用程序或OLTP系统,您可能会降低此值,以便快速显示用户反馈,或将更新放入队列以供日后处理。您可以为长时间运行的后端操作增加此值,例如数据仓库中的变换步骤,该步骤等待其他大型插入或更新操作完成。
innodb_lock_wait_timeout仅适用于
InnoDB行锁。MySQL
表锁不会在内部发生,InnoDB并且此超时不适用于等待表锁。
锁定等待超时值不适用于
启用时的
死锁innodb_deadlock_detect(默认值),因为它InnoDB
会立即检测到死锁并回滚其中一个死锁的事务。何时
innodb_deadlock_detect禁用,发生死锁时InnoDB依赖于
innodb_lock_wait_timeout事务回滚。请参见
第14.5.5.2节“死锁检测和回滚”。
innodb_lock_wait_timeout可以在运行时用SET GLOBALor
SET SESSION语句来设置。更改
GLOBAL设置需要
SUPER特权并影响后续连接的所有客户端的操作。任何客户端都可以更改SESSION设置
innodb_lock_wait_timeout,仅影响该客户端。
innodb_locks_unsafe_for_binlog
| 属性 | 值 |
|---|---|
| 命令行格式 | --innodb-locks-unsafe-for-binlog |
| 弃用 | 是 |
| 系统变量 | innodb_locks_unsafe_for_binlog |
| 范围 | 全球 |
| 动态 | 没有 |
| 类型 | 布尔 |
| 默认 | OFF |
此变量影响如何在搜索和索引扫描中InnoDB使用
间隙锁定。
innodb_locks_unsafe_for_binlog已被弃用,并将在未来的MySQL版本中被删除。
通常,InnoDB使用称为下一个键锁定的算法,该算法结合了索引行锁定和
间隙锁定。
InnoDB以这样的方式执行行级锁定,即当它搜索或扫描表索引时,它会在遇到的索引记录上设置共享锁或排它锁。因此,行级锁实际上是索引记录锁。另外,索引记录上的下一个键锁也会影响索引记录之前的间隔。也就是说,下一个键锁定是索引记录锁定,并在索引记录之前的间隔上加上间隙锁定。如果一个会话有记录的共享或排他锁R在索引中,另一个会话不能R在索引顺序中立即在间隙中插入新的索引记录
。请参见
第14.5.1节“InnoDB锁定”。
默认情况下,值为
innodb_locks_unsafe_for_binlog0(禁用),这意味着启用间隙锁定:
InnoDB对搜索和索引扫描使用下一个键锁。要启用该变量,请将其设置为1.这会导致禁用间隙锁定:InnoDB仅对索引扫描和索引扫描使用索引记录锁定。
启用innodb_locks_unsafe_for_binlog
不会禁用对外键约束检查或重复键检查使用间隙锁定。
启用的效果
innodb_locks_unsafe_for_binlog与设置事务隔离级别相同
READ COMMITTED,但有以下例外:
启用
innodb_locks_unsafe_for_binlog
是一个全局设置,会影响所有会话,而隔离级别可以全局设置为所有会话,也可以单独设置每个会话。
innodb_locks_unsafe_for_binlog
只能在服务器启动时设置,而隔离级别可以在启动时设置或在运行时更改。
READ COMMITTED因此提供更好,更灵活的控制
innodb_locks_unsafe_for_binlog。有关隔离级别对间隙锁定的影响的更多信息,请参见
第14.5.2.1节“事务隔离级别”。
启用innodb_locks_unsafe_for_binlog可能会导致幻影问题,因为其他会话可以在禁用间隙锁定时将新行插入到间隙中。假设表的id列
上有一个索引,child并且您希望读取并锁定标识符值大于100的表中的所有行,并打算稍后更新所选行中的某一列:
SELECT * FROM child WHERE id> 100 FOR UPDATE;
查询从id大于100 的第一条记录开始扫描索引。如果在该范围内的索引记录上设置的锁不锁定在间隔中进行的插入,则另一个会话可以向表中插入新行。因此,如果您要在同SELECT一个事务中再次执行
相同的事务,则会在查询返回的结果集中看到新行。这也意味着如果新项目添加到数据库中,InnoDB不保证可串行化。因此,如果
innodb_locks_unsafe_for_binlog启用,则
InnoDB至多保证隔离级别为READ COMMITTED。(冲突序列化仍然有保证。)有关幻影的更多信息,请参见
第14.5.4节“幻影行”。
启用innodb_locks_unsafe_for_binlog具有附加效果:
考虑下面的例子,从这个表开始:
CREATE TABLE t(INT NOT NULL,b INT)ENGINE = InnoDB; 插入t值(1,2),(2,3),(3,2),(4,3),(5,2); 承诺;
在这种情况下,表没有索引,因此搜索和索引扫描使用隐藏的聚簇索引进行记录锁定(请参见 第14.8.2.1节“聚簇索引和次索引”)。
假设一个客户UPDATE使用这些语句执行
:
SET autocommit = 0; UPDATE t SET b = 5 WHERE b = 3;
假设第二个客户端
UPDATE通过执行第一个客户端的语句来执行这些语句:
SET autocommit = 0; UPDATE t SET b = 4 WHERE b = 2;
由于InnoDB每个执行
UPDATE时,它首先获取用于各行的排他锁,然后确定是否对其进行修改。如果InnoDB不修改该行并被innodb_locks_unsafe_for_binlog启用,则释放该锁。否则,
InnoDB保留锁直到交易结束。这会影响事务处理,如下所示。
如果innodb_locks_unsafe_for_binlog被禁用,第一个UPDATE
获取x锁并且不释放它们中的任何一个:
X锁(1,2); 保留x锁 X锁(2,3); 更新(2,3)至(2,5); 保留x锁 X锁(3,2); 保留x锁 X锁(4,3); 更新(4,3)至(4,5); 保留x锁 X锁(5,2); 保留x锁
第二UPDATE块试图获取任何锁(因为第一个更新保留了所有行的锁),并且在第一次UPDATE提交或回退之前不会继续:
X锁(1,2); 阻止并等待第一个UPDATE提交或回滚
如果innodb_locks_unsafe_for_binlog启用,第一个UPDATE
获取x锁并释放那些不修改的行:
X锁(1,2); 解锁(1,2) X锁(2,3); 更新(2,3)至(2,5); 保留x锁 X锁(3,2); 解锁(3,2) X锁(4,3); 更新(4,3)至(4,5); 保留x锁 X锁(5,2); 解锁(5,2)
对于第二个UPDATE,
InnoDB执行
“ 半连续 ”读取,将每行的最新提交版本返回给MySQL,以便MySQL可以确定该行是否与以下WHERE
条件匹配UPDATE:
X锁(1,2); 更新(1,2)至(1,4); 保留x锁 X锁(2,3); 解锁(2,3) X锁(3,2); 更新(3,2)至(3,4); 保留x锁 X锁(4,3); 解锁(4,3) X锁(5,2); 更新(5,2)至(5,4); 保留x锁
| 属性 | 值 |
|---|---|
| 命令行格式 | --innodb-log-buffer-size=# |
| 系统变量 | innodb_log_buffer_size |
| 范围 | 全球 |
| 动态 | 没有 |
| 类型 | 整数 |
| 默认(> = 5.7.6) | 16777216 |
| 默认(<= 5.7.5) | 8388608 |
| 最小(> = 5.7.6) | 1048576 |
| 最小(<= 5.7.5) | 262144 |
| 最大 | 4294967295 |
InnoDB
用于写入磁盘上日志文件
的缓冲区的大小(以字节为单位)。引入32k和64k innodb_page_size值后,默认值从8MB变为16MB
。一个大的日志缓冲区
允许大
事务运行,而无需在事务提交之前将日志写入磁盘。因此,如果您有更新,插入或删除多行的事务,则使日志缓冲区更大可节省磁盘I / O。有关相关信息,请参阅
InnoDB内存配置,以及
第8.5.4节“优化InnoDB重做日志记录”。有关通用I / O优化建议,请参见第8.5.8节“优化InnoDB磁盘I / O”。
| 属性 | 值 |
|---|---|
| 命令行格式 | --innodb-log-checksum-algorithm=# |
| 介绍 | 5.7.8 |
| 删除 | 5.7.9 |
| 系统变量 | innodb_log_checksum_algorithm |
| 范围 | 全球 |
| 动态 | 是 |
| 类型(> = 5.7.8) | 列举 |
| 默认(> = 5.7.8) | innodb |
| 有效值(> = 5.7.8) |
|
该配置选项已被删除并被替换
innodb_log_checksums。
指定如何生成并验证存储在每个重做日志磁盘块中的
校验和。
innodb_log_checksum_algorithm支持相同的算法innodb_checksum_algorithm。以前,只有innodb算法支持重做日志磁盘块。
innodb_log_checksum_algorithm=innodb是默认设置。
严格的表单一样innodb,
crc32和none,只是InnoDB暂停,如果遇到校验和值在同一重做日志的组合。您只能在全新的实例中使用严格的设置。严格的设置有点快,因为它们不需要计算新的和旧的校验和值来在磁盘读取期间同时接受这两个值。
下表显示了之间的区别
none,innodb和
crc32选项值,和他们同行的严格。none,
innodb并将crc32指定类型的校验和值写入每个数据块,但为了兼容性,在读取操作期间验证块时接受任何其他校验和值。每个选项的严格形式只能识别一种校验和,这使得验证更快,但要求InnoDB实例中的所有
重做日志都是在相同的innodb_log_checksum_algorithm值下创建的
。
表14.15 innodb_log_checksum_algorithm设置
| 值 | 生成的校验和(写入时) | 允许的校验和(阅读时) |
|---|---|---|
| 没有 | 一个常数。 | 任何校验的产生通过none,
innodb或crc32。 |
| InnoDB的 | 用软件计算校验和,使用原始算法
InnoDB。 |
任何校验的产生通过none,
innodb或crc32。 |
| CRC32 | 使用该crc32算法计算校验和,可能使用硬件辅助。 |
任何校验的产生通过none,
innodb或crc32。 |
| strict_none | 一个常数 | 只有生成的校验和none。 |
| strict_innodb | 用软件计算校验和,使用原始算法
InnoDB。 |
只有生成的校验和innodb。 |
| strict_crc32 | 使用该crc32算法计算校验和,可能使用硬件辅助。 |
只有生成的校验和crc32。 |
| 属性 | 值 |
|---|---|
| 命令行格式 | --innodb-log-checksums=# |
| 介绍 | 5.7.9 |
| 系统变量 | innodb_log_checksums |
| 范围 | 全球 |
| 动态 | 是 |
| 类型 | 布尔 |
| 默认 | ON |
启用或禁用重做日志页面的校验和。
innodb_log_checksums替换
innodb_log_checksum_algorithm。
innodb_log_checksums=ON启用CRC-32C重做日志页面的
校验和算法。当innodb_log_checksums禁用时,重做日志页面校验和字段的内容将被忽略。
重做日志标题页和重做日志检查点页面上的校验和从不禁用。
| 属性 | 值 |
|---|---|
| 命令行格式 | --innodb-log-compressed-pages=# |
| 系统变量 | innodb_log_compressed_pages |
| 范围 | 全球 |
| 动态 | 是 |
| 类型 | 布尔 |
| 默认 | ON |
指定是否将重新压缩的 页面的图像 写入 重做日志。对压缩数据进行更改时可能会发生重新压缩。
innodb_log_compressed_pages默认情况下启用,以防止zlib在恢复期间使用不同版本的压缩算法时可能发生的损坏。如果您确定
zlib版本不会更改,则可以禁用innodb_log_compressed_pages以减少修改压缩数据的工作负载的重做日志生成。
要度量启用或禁用的效果
innodb_log_compressed_pages,请比较相同工作负载下两个设置的重做日志生成。测量重做日志生成的选项包括观察输出部分中
的Log sequence number(LSN)
,或监视
写入重做日志文件的字节数的状态。
LOGSHOW ENGINE
INNODB STATUSInnodb_os_log_written
有关相关信息,请参见 第14.9.1.6节“OLTP工作负载的压缩”。
| 属性 | 值 |
|---|---|
| 命令行格式 | --innodb-log-file-size=# |
| 系统变量 | innodb_log_file_size |
| 范围 | 全球 |
| 动态 | 没有 |
| 类型 | 整数 |
| 默认 | 50331648 |
| 最低(> = 5.7.11) | 4194304 |
| 最小(<= 5.7.10) | 1048576 |
| 最大 | 512GB / innodb_log_files_in_group |
在每个字节大小日志文件在日志组。日志文件(innodb_log_file_size*
innodb_log_files_in_group)的组合大小不能超过略小于512GB的最大值。例如,一对255 GB的日志文件接近极限,但不超过它。默认值是48MB。
通常,日志文件的组合大小应该足够大,以便服务器可以消除工作负载活动中的高峰和低谷,这通常意味着有足够的重做日志空间来处理一个多小时的写入活动。值越大,缓冲池中所需的检查点刷新活动就越少,从而节省磁盘I / O。较大的日志文件也会使崩溃恢复速度变慢,尽管对MySQL 5.5和更高版本中的恢复性能的改进使得日志文件的大小更小。
innodb_log_file_sizeMySQL 5.7.11中
的最小值从1MB增加到4MB。
相关信息请参见 InnoDB日志文件配置。有关通用I / O优化建议,请参见 第8.5.8节“优化InnoDB磁盘I / O”。
| 属性 | 值 |
|---|---|
| 命令行格式 | --innodb-log-files-in-group=# |
| 系统变量 | innodb_log_files_in_group |
| 范围 | 全球 |
| 动态 | 没有 |
| 类型 | 整数 |
| 默认 | 2 |
| 最低限度 | 2 |
| 最大 | 100 |
数日志文件
中日志组。
InnoDB以循环方式写入文件。默认(推荐)值是2.文件的位置由<文件名>指定
innodb_log_group_home_dir。日志文件(innodb_log_file_size*
innodb_log_files_in_group)的组合大小可以高达512GB。
相关信息请参见 InnoDB日志文件配置。
| 属性 | 值 |
|---|---|
| 命令行格式 | --innodb-log-group-home-dir=dir_name |
| 系统变量 | innodb_log_group_home_dir |
| 范围 | 全球 |
| 动态 | 没有 |
| 类型 | 目录名称 |
InnoDB
重做日志文件
的目录路径,其编号由指定
innodb_log_files_in_group。如果你没有指定任何InnoDB日志变量,默认是在MySQL数据目录中创建两个名为ib_logfile0和的
文件
ib_logfile1。日志文件大小由innodb_log_file_size系统变量给出
。
相关信息请参见 InnoDB日志文件配置。
| 属性 | 值 |
|---|---|
| 命令行格式 | --innodb-log-write-ahead-size=# |
| 介绍 | 5.7.4 |
| 系统变量 | innodb_log_write_ahead_size |
| 范围 | 全球 |
| 动态 | 是 |
| 类型 | 整数 |
| 默认 | 8192 |
| 最低限度 | 512 (log file block size) |
| 最大 | Equal to innodb_page_size |
重做日志的预写块大小,以字节为单位。要避免“ 读写 ”,请设置
innodb_log_write_ahead_size为与操作系统或文件系统缓存块大小相匹配。由于重做日志的预写块大小与操作系统或文件系统高速缓存块大小之间的不匹配,重做日志块未完全缓存到操作系统或文件系统时发生了写入时读写。
有效值
innodb_log_write_ahead_size是InnoDB日志文件块大小的倍数(2 ^ n)。最小值是InnoDB日志文件块大小(512)。指定最小值时不发生预写。最大值等于
innodb_page_size。如果您指定的值
innodb_log_write_ahead_size大于该innodb_page_size
值,则该innodb_log_write_ahead_size
值将被截断为该
innodb_page_size值。
将innodb_log_write_ahead_size
操作系统或文件系统缓存块大小设置得太低会导致
“ 读写 ”。fsync由于一次写入多个块,因此将该值设置得过高可能会对日志文件写入的性能产生轻微影响。
| 属性 | 值 |
|---|---|
| 命令行格式 | --innodb-lru-scan-depth=# |
| 系统变量 | innodb_lru_scan_depth |
| 范围 | 全球 |
| 动态 | 是 |
| 类型(64位平台) | 整数 |
| 类型(32位平台) | 整数 |
| 默认(64位平台) | 1024 |
| 默认(32位平台) | 1024 |
| 最低(64位平台) | 100 |
| 最低(32位平台) | 100 |
| 最大(64位平台) | 2**64-1 |
| 最大(32位平台) | 2**32-1 |
影响缓冲池刷新操作
的算法和启发式的参数。性能专家主要关注调整I / O密集型工作负载。它指定每个缓冲池实例在缓冲池LRU页面列表中多少,页面清理器线程扫描寻找要刷新的脏页面。这是每秒执行一次的后台操作。
InnoDB
小于默认值的设置通常适用于大多数工作负载。比所需值高得多的值可能会影响性能。只有在典型工作负载下具有空闲I / O容量的情况下才考虑增加此值。相反,如果写密集型工作负载使您的I / O容量达到饱和,请降低该值,尤其是在大型缓冲池的情况下。
调整时innodb_lru_scan_depth,从低值开始,向上配置设置,目标很少看到零空闲页面。此外,请考虑调整innodb_lru_scan_depth更改缓冲池实例的数量,因为
innodb_lru_scan_depth*
innodb_buffer_pool_instances
定义页面清理器线程每秒执行的工作量。
有关相关信息,请参见 第14.6.3.7节“微调InnoDB缓冲池刷新”。有关通用I / O优化建议,请参见 第8.5.8节“优化InnoDB磁盘I / O”。
| 属性 | 值 |
|---|---|
| 命令行格式 | --innodb-max-dirty-pages-pct=# |
| 系统变量 | innodb_max_dirty_pages_pct |
| 范围 | 全球 |
| 动态 | 是 |
| 类型 | 数字 |
| 默认 | 75 |
| 最低限度 | 0 |
| 最大(> = 5.7.5) | 99.99 |
| 最大(<= 5.7.4) | 99 |
InnoDB尝试
从缓冲池中清除数据,
以便脏页面的百分比不超过此值。默认值是75。
该
innodb_max_dirty_pages_pct
设置确定了冲洗活动的目标。它不会影响冲洗的速度。有关管理刷新速率的信息,请参见第14.6.3.6节“配置InnoDB缓冲池刷新
”。
有关相关信息,请参见 第14.6.3.7节“微调InnoDB缓冲池刷新”。有关通用I / O优化建议,请参见 第8.5.8节“优化InnoDB磁盘I / O”。
innodb_max_dirty_pages_pct_lwm
| 属性 | 值 |
|---|---|
| 命令行格式 | --innodb-max-dirty-pages-pct-lwm=# |
| 系统变量 | innodb_max_dirty_pages_pct_lwm |
| 范围 | 全球 |
| 动态 | 是 |
| 类型 | 数字 |
| 默认 | 0 |
| 最低限度 | 0 |
| 最大(> = 5.7.5) | 99.99 |
| 最大(<= 5.7.4) | 99 |
定义代表的比例低水位标记 脏页,在其中预冲洗能够控制脏页比例。默认值为0将完全禁用预冲洗行为。有关更多信息,请参见 第14.6.3.7节“微调InnoDB缓冲池刷新”。
| 属性 | 值 |
|---|---|
| 命令行格式 | --innodb-max-purge-lag=# |
| 系统变量 | innodb_max_purge_lag |
| 范围 | 全球 |
| 动态 | 是 |
| 类型 | 整数 |
| 默认 | 0 |
| 最低限度 | 0 |
| 最大 | 4294967295 |
定义清除队列的最大长度。默认值0表示没有限制(没有延迟)。
当清除操作滞后时INSERT,
使用此选项可强制延迟
UPDATE和
DELETE执行
操作(请参见第14.3节“InnoDB多版本控制”)。
该InnoDB交易系统认为有通过索引记录删除标记事务的列表
UPDATE或
DELETE操作。列表的长度代表
purge_lag值。如果
purge_lag超过
innodb_max_purge_lag,
INSERT,
UPDATE,和
DELETE操作被延迟。
为防止在purge_lag变得巨大的极端情况下出现过度延迟
,可以通过设置innodb_max_purge_lag_delay
配置选项来限制延迟
。延迟是在清洗批次开始时计算的。
对于有问题的工作负载,典型设置可能是100万,假设事务很小,只有100个字节大小,并且允许有100MB未清理的
InnoDB表行。
滞后值显示为InnoDB Monitor输出TRANSACTIONS部分中
的历史列表长度
。该示例输出中滞后值为20:
------------ 交易 ------------ Trx id counter 0 290328385 清除trx的n:o <0 290315608 undo n:o <0 17 历史列表长度20
有关通用I / O优化建议,请参见 第8.5.8节“优化InnoDB磁盘I / O”。
| 属性 | 值 |
|---|---|
| 命令行格式 | --innodb-max-purge-lag-delay=# |
| 系统变量 | innodb_max_purge_lag_delay |
| 范围 | 全球 |
| 动态 | 是 |
| 类型 | 整数 |
| 默认 | 0 |
| 最低限度 | 0 |
指定由innodb_max_purge_lag
配置选项施加的延迟的最大延迟(以微秒为单位)
。非零值表示根据公式计算出的延迟时间的上限值
innodb_max_purge_lag。默认值为零意味着延迟时间间隔没有上限。
有关通用I / O优化建议,请参见 第8.5.8节“优化InnoDB磁盘I / O”。
| 属性 | 值 |
|---|---|
| 命令行格式 | --innodb-max-undo-log-size=# |
| 介绍 | 5.7.5 |
| 系统变量 | innodb_max_undo_log_size |
| 范围 | 全球 |
| 动态 | 是 |
| 类型 | 整数 |
| 默认 | 1073741824 |
| 最低限度 | 10485760 |
| 最大 | 2**64-1 |
定义撤消表空间的阈值大小。如果撤消表空间超过阈值,innodb_undo_log_truncate则启用时可将其标记为截断
。默认值是1073741824字节(1024兆字节)。
有关更多信息,请参见 第14.7.8节“截断撤消表空间”。
innodb_merge_threshold_set_all_debug
| 属性 | 值 |
|---|---|
| 命令行格式 | --innodb-merge-threshold-set-all-debug=# |
| 介绍 | 5.7.6 |
| 系统变量 | innodb_merge_threshold_set_all_debug |
| 范围 | 全球 |
| 动态 | 是 |
| 类型 | 整数 |
| 默认 | 50 |
| 最低限度 | 1 |
| 最大 | 50 |
MERGE_THRESHOLD
为当前位于字典缓存中的所有索引
重写当前设置的索引页定义页面完全百分比值。该选项仅在使用CMake选项编译调试支持时可用。有关相关信息,请参见
第14.6.13节“为索引页面配置合并阈值”。
WITH_DEBUG
| 属性 | 值 |
|---|---|
| 命令行格式 | --innodb-monitor-disable=[counter|module|pattern|all] |
| 系统变量 | innodb_monitor_disable |
| 范围 | 全球 |
| 动态 | 是 |
| 类型 | 串 |
禁用InnoDB
度量标准计数器。计数器数据可以使用INFORMATION_SCHEMA.INNODB_METRICS
表查询
。有关使用信息,请参见
第14.15.6节“InnoDB INFORMATION_SCHEMA度量标准表”。
innodb_monitor_disable='latch'禁用统计信息收集
SHOW ENGINE
INNODB MUTEX。有关更多信息,请参见
第13.7.5.15节“SHOW ENGINE语法”。
| 属性 | 值 |
|---|---|
| 命令行格式 | --innodb-monitor-enable=[counter|module|pattern|all] |
| 系统变量 | innodb_monitor_enable |
| 范围 | 全球 |
| 动态 | 是 |
| 类型 | 串 |
启用InnoDB
指标计数器。计数器数据可以使用INFORMATION_SCHEMA.INNODB_METRICS
表查询
。有关使用信息,请参见
第14.15.6节“InnoDB INFORMATION_SCHEMA度量标准表”。
innodb_monitor_enable='latch'启用统计信息收集
SHOW ENGINE
INNODB MUTEX。有关更多信息,请参见
第13.7.5.15节“SHOW ENGINE语法”。
| 属性 | 值 |
|---|---|
| 命令行格式 | --innodb-monitor-reset=[counter|module|pattern|all] |
| 系统变量 | innodb_monitor_reset |
| 范围 | 全球 |
| 动态 | 是 |
| 类型 | 串 |
InnoDB
度量指标计数器
的计数值重置
为零。计数器数据可以使用INFORMATION_SCHEMA.INNODB_METRICS
表查询
。有关使用信息,请参见
第14.15.6节“InnoDB INFORMATION_SCHEMA度量标准表”。
innodb_monitor_reset='latch'重置报告的统计数据
SHOW ENGINE
INNODB MUTEX。有关更多信息,请参见
第13.7.5.15节“SHOW ENGINE语法”。
| 属性 | 值 |
|---|---|
| 命令行格式 | --innodb-monitor-reset-all=[counter|module|pattern|all] |
| 系统变量 | innodb_monitor_reset_all |
| 范围 | 全球 |
| 动态 | 是 |
| 类型 | 串 |
重置InnoDB
指标计数器的所有值(最小值,最大值等)
。计数器数据可以使用INFORMATION_SCHEMA.INNODB_METRICS
表查询
。有关使用信息,请参见
第14.15.6节“InnoDB INFORMATION_SCHEMA度量标准表”。
| 属性 | 值 |
|---|---|
| 命令行格式 | --innodb-numa-interleave=# |
| 介绍 | 5.7.9 |
| 系统变量 | innodb_numa_interleave |
| 范围 | 全球 |
| 动态 | 没有 |
| 类型 | 布尔 |
| 默认 | OFF |
启用NUMA交错存储器策略以分配InnoDB缓冲池。当
innodb_numa_interleave启用时,NUMA内存策略设置为MPOL_INTERLEAVE对mysqld的进程。后
InnoDB缓冲池分配,在NUMA内存策略设置回MPOL_DEFAULT。为了使innodb_numa_interleave选项可用,MySQL必须在启用NUMA的Linux系统上编译。
从MySQL 5.7.17开始,CMakeWITH_NUMA根据当前平台是否NUMA支持设置默认
值。有关更多信息,请参见
第2.9.4节“MySQL源配置选项”。
| 属性 | 值 |
|---|---|
| 命令行格式 | --innodb-old-blocks-pct=# |
| 系统变量 | innodb_old_blocks_pct |
| 范围 | 全球 |
| 动态 | 是 |
| 类型 | 整数 |
| 默认 | 37 |
| 最低限度 | 5 |
| 最大 | 95 |
指定用于旧块子列表的InnoDB
缓冲池的近似百分比
。值的范围是5到95.默认值是37(即池的3/8)。通常与组合使用
。
innodb_old_blocks_time
有关更多信息,请参见 第14.6.3.4节“使缓冲池抗扫描”。有关缓冲池管理, LRU算法和 驱逐策略的信息,请参见 第14.6.3.1节“InnoDB缓冲池”。
| 属性 | 值 |
|---|---|
| 命令行格式 | --innodb-old-blocks-time=# |
| 系统变量 | innodb_old_blocks_time |
| 范围 | 全球 |
| 动态 | 是 |
| 类型 | 整数 |
| 默认 | 1000 |
| 最低限度 | 0 |
| 最大 | 2**32-1 |
非零值可防止 缓冲池由仅在短时间内引用的数据填充,例如在全表扫描期间。增加此值可以防止全表扫描干扰缓存池中缓存的数据。
指定插入旧子列表的块在其第一次访问后必须保留多长时间(以毫秒为单位),然后才能将其移至新子列表。如果值为0,则插入旧子列表的块将在第一次访问时立即移动到新子列表中,无论插入后多久发生访问。如果该值大于0,则块会保留在旧的子列表中,直到第一次访问之后至少发生数毫秒的访问为止。例如,值为1000会导致块在第一次访问后停留在旧子列表中1秒钟,然后才有资格移动到新子列表。
缺省值是1000。
这个配置选项通常与其结合使用
innodb_old_blocks_pct。有关更多信息,请参见
第14.6.3.4节“使缓冲池抗扫描”。有关缓冲池管理,
LRU算法和
驱逐策略的信息,请参见
第14.6.3.1节“InnoDB缓冲池”。
innodb_online_alter_log_max_size
| 属性 | 值 |
|---|---|
| 命令行格式 | --innodb-online-alter-log-max-size=# |
| 系统变量 | innodb_online_alter_log_max_size |
| 范围 | 全球 |
| 动态 | 是 |
| 类型 | 整数 |
| 默认 | 134217728 |
| 最低限度 | 65536 |
| 最大 | 2**64-1 |
指定表的联机DDL操作期间使用的临时日志文件大小的上限(以字节为单位)InnoDB。对于正在创建的每个索引或正在更改的表,都有一个这样的日志文件。该日志文件存储在DDL操作期间插入,更新或删除的表中的数据。当需要时,临时日志文件将被扩展
innodb_sort_buffer_size,直到达到最大值
innodb_online_alter_log_max_size。如果临时日志文件超过了大小上限,则
ALTER TABLE操作失败,所有未提交的并发DML操作都会回滚。因此,此选项的较大值允许在联机DDL操作期间发生更多DML,但是也可以延长DDL操作结束时的时间间隔,以便锁定表以应用日志中的数据。
| 属性 | 值 |
|---|---|
| 命令行格式 | --innodb-open-files=# |
| 系统变量 | innodb_open_files |
| 范围 | 全球 |
| 动态 | 没有 |
| 类型 | 整数 |
| 默认 | -1 (autosized) |
| 最低限度 | 10 |
| 最大 | 4294967295 |
只有使用多个InnoDB
表空间时,此配置选项才是相关的
。它指定了MySQL一次可以保持打开的最大.ibd
文件数量
。最小值为10.如果innodb_file_per_table未启用,则默认值为300
,而较高值为300,
table_open_cache否则为。
用于文件的文件描述符仅.ibd用于InnoDB表格。它们独立于--open-files-limit服务器选项指定的那些
,并且不影响表缓存的操作。有关通用I / O优化建议,请参见
第8.5.8节“优化InnoDB磁盘I / O”。
| 属性 | 值 |
|---|---|
| 命令行格式 | --innodb-optimize-fulltext-only=# |
| 系统变量 | innodb_optimize_fulltext_only |
| 范围 | 全球 |
| 动态 | 是 |
| 类型 | 布尔 |
| 默认 | OFF |
改变表格的OPTIMIZE TABLE
操作方式InnoDB。打算在InnoDB具有FULLTEXT索引的表的
维护操作期间暂时启用
。
默认情况下,OPTIMIZE TABLE
重新组织表中的聚集索引中的数据
。启用此选项时,
OPTIMIZE TABLE跳过表数据的重新组织,而是处理InnoDB FULLTEXT索引的新添加,删除和更新的标记数据
。有关更多信息,请参阅
优化InnoDB全文索引。
| 属性 | 值 |
|---|---|
| 命令行格式 | --innodb-optimize-point-storage=# |
| 介绍 | 5.7.5 |
| 删除 | 5.7.6 |
| 系统变量 | innodb_optimize_point_storage |
| 范围 | 会议 |
| 动态 | 是 |
| 类型 | 布尔 |
| 默认 | OFF |
在创建一个类型的列之前启用此变量,
POINT以将POINT
数据类型内部存储为可变长度
BLOB数据。
| 属性 | 值 |
|---|---|
| 命令行格式 | --innodb-page-cleaners=# |
| 介绍 | 5.7.4 |
| 系统变量 | innodb_page_cleaners |
| 范围 | 全球 |
| 动态 | 没有 |
| 类型 | 整数 |
| 默认(> = 5.7.8) | 4 |
| 默认(<= 5.7.7) | 1 |
| 最低限度 | 1 |
| 最大 | 64 |
从缓冲池实例中刷新脏页的页面清理器线程的数量。页面清理器线程执行清空列表和LRU刷新。在MySQL 5.6中引入了单页面清理器线程,以便从InnoDB主线程卸载缓冲池清除工作。在MySQL 5.7中,InnoDB为多个页面清理器线程提供支持。值为1的维护MySQL 5.7之前的配置,其中有一个页面清理器线程。当存在多个页面清理器线程时,将为每个缓冲池实例分配缓冲池清理任务给闲置的页面清理器线程。该innodb_page_cleanersMySQL 5.7中默认值从1改为4。如果页面清理线程的数量超过缓冲池实例的数量,innodb_page_cleaners
则会自动设置为与
innodb_buffer_pool_instances。
如果在将缓冲池实例中的脏页面刷新到数据文件时,您的工作负载被写入IO界限,并且系统硬件具有可用容量,则增加页面清理器线程数可能有助于提高写入IO吞吐量。
多线程页面清理器支持扩展到MySQL 5.7中的关闭和恢复阶段。
该setpriority()系统调用是用来在那里它被支持的Linux平台,并且其中
的mysqld执行用户被授权给
page_cleaner线程优先于其他MySQL和InnoDB线程帮助页面刷新保持与当前工作负载的速度。
setpriority()支持由此InnoDB启动消息指示
:
[注意] InnoDB:如果mysqld执行用户被授权,页面清理 线程优先级可以改变。请参阅setpriority()的手册页。
对于不由systemd管理服务器启动和关闭的系统,可以在中配置mysqld执行用户授权
/etc/security/limits.conf。例如,如果mysqld在mysql用户下运行
,则可以mysql通过将这些行添加到以下来授权
用户
/etc/security/limits.conf:
mysql很难很好-20 mysql软很好-20
对于systemd受管系统,通过LimitNICE=-20在本地化系统配置文件中指定可以实现相同的目的。例如,创建一个名为override.confin
的文件
/etc/systemd/system/mysqld.service.d/override.conf
并添加此条目:
[服务] LimitNICE = -20
创建或更改后override.conf,重新加载systemd配置,然后告诉systemd重新启动MySQL服务:
systemctl守护进程重新加载 systemctl restart mysqld#RPM平台 systemctl重启mysql#Debian平台
有关使用本地化systemd配置文件的更多信息,请参阅 配置systemd for MySQL。
授权mysqld执行用户后,使用cat命令验证Nice为mysqld进程配置的限制
:
shell> cat / proc / mysqld_pid/ limits | grep很好
最大不错的优先级18446744073709551596 18446744073709551596
| 属性 | 值 |
|---|---|
| 命令行格式 | --innodb-page-size=#k |
| 系统变量 | innodb_page_size |
| 范围 | 全球 |
| 动态 | 没有 |
| 类型 | 列举 |
| 默认 | 16384 |
| 有效值(> = 5.7.6) |
|
| 有效值(<= 5.7.5) |
|
指定MySQL
实例中
所有表空间的页面大小。您可以使用值64k,32k
(默认值),或者
来指定页面大小。或者,您可以以字节为单位指定页面大小(65536,32768,16384,8192,4096)。
InnoDB
16k8k4k
innodb_page_size只能在初始化MySQL实例之前进行配置,之后不能更改。如果未指定值,则使用默认页面大小初始化实例。请参见
第14.6.1节“InnoDB启动配置”。
在MySQL 5.7中增加了对32k和64k页面大小的支持。对于32k和64k页面大小,最大行长度大约为16000字节。
ROW_FORMAT=COMPRESSED在innodb_page_size设置为32KB或64KB 时不受支持
。因为innodb_page_size=32k,范围的大小是2MB。因为innodb_page_size=64k,范围大小是4MB。
innodb_log_buffer_size在使用32k或64k页面大小时应该设置为至少16M(默认值)。
默认的16KB页面大小或更大适用于各种工作负载,特别是涉及涉及批量更新的表扫描和DML操作的查询。对于
涉及许多小写入的OLTP工作负载,较小的页面大小可能更有效,其中当单个页面包含许多行时,争用可能成为问题。较小的页面对于SSD存储设备也可能是有效的,
SSD存储设备通常使用小块大小。保持
InnoDB页面大小接近存储设备块大小可将重写到磁盘的未更改数据量减至最少。
第一个系统表空间数据文件(ibdata1)的最小文件大小因innodb_page_size值而异
。有关innodb_data_file_path
更多信息,请参阅选项说明。
有关通用I / O优化建议,请参见 第8.5.8节“优化InnoDB磁盘I / O”。
| 属性 | 值 |
|---|---|
| 命令行格式 | --innodb-print-all-deadlocks=# |
| 系统变量 | innodb_print_all_deadlocks |
| 范围 | 全球 |
| 动态 | 是 |
| 类型 | 布尔 |
| 默认 | OFF |
当启用该选项,所有信息
死锁在
InnoDB用户交易被记录在
mysqld 错误日志。否则,只能使用该SHOW ENGINE INNODB
STATUS命令查看有关最后一个死锁的信息。偶尔的
InnoDB僵局并不一定是个问题,因为InnoDB立即检测到状况并自动回滚其中一项交易。如果应用程序没有适当的错误处理逻辑来检测回滚并重试其操作,则可以使用此选项来排查为什么发生死锁。大量的死锁可能表示需要重构发布DML的事务
或SELECT ... FOR
UPDATE多个表的语句,以便每个事务以相同的顺序访问表,从而避免死锁状况。
有关相关信息,请参见 第14.5.5节“InnoDB中的死锁”。
| 属性 | 值 |
|---|---|
| 命令行格式 | --innodb-purge-batch-size=# |
| 系统变量 | innodb_purge_batch_size |
| 范围 | 全球 |
| 动态 | 是 |
| 类型 | 整数 |
| 默认 | 300 |
| 最低限度 | 1 |
| 最大 | 5000 |
定义从历史列表中清除一个批次中解析和处理的撤消日志页面的数量
。在多线程吹扫的配置中,协调器净化线程分割innodb_purge_batch_size通过
innodb_purge_threads并分配该数量的页的每个吹扫线程。该
innodb_purge_batch_size选项还定义了在通过撤消日志每128次迭代后清除释放的撤消日志页的数量。
该innodb_purge_batch_size选件适用于结合innodb_purge_threads
设置进行高级性能调整。大多数MySQL用户不需要改变
innodb_purge_batch_size默认值。
有关相关信息,请参见 第14.6.11节“配置InnoDB清除调度”。
| 属性 | 值 |
|---|---|
| 命令行格式 | --innodb-purge-threads=# |
| 系统变量 | innodb_purge_threads |
| 范围 | 全球 |
| 动态 | 没有 |
| 类型 | 整数 |
| 默认(> = 5.7.8) | 4 |
| 默认(<= 5.7.7) | 1 |
| 最低限度 | 1 |
| 最大 | 32 |
专门用于InnoDB
清除操作的后台线程的数量
。最小值为1表示清除操作总是由后台线程执行,而不是主线程的一部分
。在一个或多个后台线程中运行清除操作有助于减少内部争用
InnoDB,提高可伸缩性。将该值增加到大于1会产生许多单独的清除线程,这可以提高在多个表上执行DML操作的系统的效率
。最大值是32。
有关相关信息,请参见 第14.6.11节“配置InnoDB清除调度”。
innodb_purge_rseg_truncate_frequency
| 属性 | 值 |
|---|---|
| 命令行格式 | --innodb-purge-rseg-truncate-frequency=# |
| 介绍 | 5.7.5 |
| 系统变量 | innodb_purge_rseg_truncate_frequency |
| 范围 | 全球 |
| 动态 | 是 |
| 类型 | 整数 |
| 默认 | 128 |
| 最低限度 | 1 |
| 最大 | 128 |
定义清除系统根据调用清除的次数释放回滚段的频率。撤消表空间不能被截断,直到其回退段被释放。通常情况下,清除系统每调用一次清除128次就释放一次回滚段。默认值为128.减小此值将增加清除线程释放回滚段的频率。
innodb_purge_rseg_truncate_frequency旨在用于
innodb_undo_log_truncate。有关更多信息,请参见
第14.7.8节“截断撤消表空间”。
| 属性 | 值 |
|---|---|
| 命令行格式 | --innodb-random-read-ahead=# |
| 系统变量 | innodb_random_read_ahead |
| 范围 | 全球 |
| 动态 | 是 |
| 类型 | 布尔 |
| 默认 | OFF |
启用随机
预读技术来优化InnoDBI / O。
有关不同类型的预读请求的性能注意事项的详细信息,请参见 第14.6.3.5节“配置InnoDB缓冲池预取(预读)”。有关通用I / O优化建议,请参见 第8.5.8节“优化InnoDB磁盘I / O”。
| 属性 | 值 |
|---|---|
| 命令行格式 | --innodb-read-ahead-threshold=# |
| 系统变量 | innodb_read_ahead_threshold |
| 范围 | 全球 |
| 动态 | 是 |
| 类型 | 整数 |
| 默认 | 56 |
| 最低限度 | 0 |
| 最大 | 64 |
控制线性的灵敏度
预读的是
InnoDB使用预取页入
缓冲器池。如果
InnoDB至少innodb_read_ahead_threshold从一个范围
(64页)中按顺序读取
页面,它将启动对整个后续范围的异步读取。值的允许范围是0到64.值为0将禁用预读。对于缺省值56,
InnoDB必须从一定范围内按顺序读取至少56页,以启动以下范围的异步读取。
了解通过预读机制来读取多少页面,以及这些页面中有多少从缓冲池中被删除而无需被访问,在微调innodb_read_ahead_threshold
设置时会很有用
。SHOW
ENGINE INNODB STATUS输出显示对抗来自信息
Innodb_buffer_pool_read_ahead
和
Innodb_buffer_pool_read_ahead_evicted
全局状态变量,其报告的页数带入缓冲池的预读请求,以及这些页面的数量驱逐分别从缓冲池而没有被访问。状态变量报告自上次服务器重新启动以来的全局值。
SHOW ENGINE
INNODB STATUS还显示了读取预读页面的速率以及这些页面被驱逐而未被访问的速率。每秒平均值基于自上次调用以来收集的统计信息,SHOW ENGINE INNODB STATUS并显示在输出BUFFER POOL AND MEMORY
部分中
SHOW ENGINE
INNODB STATUS。
有关更多信息,请参见 第14.6.3.5节“配置InnoDB缓冲池预取(预读)”。有关通用I / O优化建议,请参见 第8.5.8节“优化InnoDB磁盘I / O”。
| 属性 | 值 |
|---|---|
| 命令行格式 | --innodb-read-io-threads=# |
| 系统变量 | innodb_read_io_threads |
| 范围 | 全球 |
| 动态 | 没有 |
| 类型 | 整数 |
| 默认 | 4 |
| 最低限度 | 1 |
| 最大 | 64 |
用于读取操作的I / O线程数
InnoDB。它与写入线程相对应innodb_write_io_threads。有关更多信息,请参见
第14.6.7节“配置背景InnoDB I / O线程数”。有关通用I / O优化建议,请参见
第8.5.8节“优化InnoDB磁盘I / O”。
在Linux系统上运行多个MySQL服务器(通常超过12)与默认设置
innodb_read_io_threads,
innodb_write_io_threads以及Linux的aio-max-nr设置可以超过系统限制。理想情况下,增加
aio-max-nr设置; 作为一种解决方法,您可以减少一个或两个MySQL配置选项的设置。
| 属性 | 值 |
|---|---|
| 命令行格式 | --innodb-read-only=# |
| 系统变量 | innodb_read_only |
| 范围 | 全球 |
| 动态 | 没有 |
| 类型 | 布尔 |
| 默认 | OFF |
InnoDB以只读模式
启动。用于在只读介质上分发数据库应用程序或数据集。也可以用于数据仓库以在多个实例之间共享相同的数据目录。有关更多信息,请参见第14.6.2节“将InnoDB配置为只读操作”。
| 属性 | 值 |
|---|---|
| 命令行格式 | --innodb-replication-delay=# |
| 系统变量 | innodb_replication_delay |
| 范围 | 全球 |
| 动态 | 是 |
| 类型 | 整数 |
| 默认 | 0 |
| 最低限度 | 0 |
| 最大 | 4294967295 |
如果innodb_thread_concurrency
达到从属服务器上的复制线程延迟(以毫秒为单位)。
| 属性 | 值 |
|---|---|
| 命令行格式 | --innodb-rollback-on-timeout |
| 系统变量 | innodb_rollback_on_timeout |
| 范围 | 全球 |
| 动态 | 没有 |
| 类型 | 布尔 |
| 默认 | OFF |
InnoDB 默认情况下,仅回滚事务超时的最后一条语句。如果
--innodb_rollback_on_timeout指定,则事务超时会导致
InnoDB中止并回滚整个事务。
如果启动事务语句是
START
TRANSACTION或
BEGIN
语句,则回滚不会取消该语句。进一步的SQL语句成为交易的一部分,直到发生COMMIT,
ROLLBACK或某些SQL语句导致隐式提交。
有关更多信息,请参见 第14.21.4节“InnoDB错误处理”。
| 属性 | 值 |
|---|---|
| 命令行格式 | --innodb-rollback-segments=# |
| 系统变量 | innodb_rollback_segments |
| 范围 | 全球 |
| 动态 | 是 |
| 类型 | 整数 |
| 默认 | 128 |
| 最低限度 | 1 |
| 最大 | 128 |
定义回滚段的数量
由使用InnoDB。
一个回滚段始终分配给系统表空间,并且32个回滚段保留供临时表使用,并驻留在临时表空间(ibtmp1)中。要为生成撤消记录的数据修改事务分配额外的回滚段,
innodb_rollback_segments必须将其设置为大于33的值。如果配置单独的撤消表空间,系统表空间中的回滚段将呈现为非活动状态。每个回滚段最多可以支持1023个数据修改事务。
当innodb_rollback_segments
设定为32以下时,InnoDB小时将一个回滚段分配给系统表空间,将32分配给临时表空间(ibtmp1)。
当innodb_rollback_segments
设置为大于32的值时,InnoDB
将一个回滚段分配给系统表空间,将32分配给临时表空间(ibtmp1)和其他回滚段以撤消表空间(如果存在)。如果撤消表空间不存在,则将额外的回滚段分配给系统表空间。
尽管您可以增加或减少使用的回滚段InnoDB的数量,但系统中物理存在的回滚段的数量不会减少。因此,您可能从此参数的值较低开始逐渐增加值,以避免分配不需要的回滚段。该
innodb_rollback_segments
默认值是128,这也是最大值。
有关回滚段的更多信息,请参见 第14.3节“InnoDB多版本控制”。有关配置单独的撤消表空间的信息,请参见 第14.7.7节“配置撤消表空间”。
innodb_saved_page_number_debug
| 属性 | 值 |
|---|---|
| 命令行格式 | --innodb-saved-page-number-debug=# |
| 系统变量 | innodb_saved_page_number_debug |
| 范围 | 全球 |
| 动态 | 是 |
| 类型 | 整数 |
| 默认 | 0 |
| 最大 | 2**23-1 |
保存页码。设置
innodb_fil_make_page_dirty_debug
选项会污染页面定义的页面
innodb_saved_page_number_debug。该
innodb_saved_page_number_debug选项仅在使用CMake选项编译调试支持时可用
。
WITH_DEBUG
| 属性 | 值 |
|---|---|
| 命令行格式 | --innodb-sort-buffer-size=# |
| 系统变量 | innodb_sort_buffer_size |
| 范围 | 全球 |
| 动态 | 没有 |
| 类型 | 整数 |
| 默认 | 1048576 |
| 最低限度 | 65536 |
| 最大 | 67108864 |
指定用于在创建InnoDB索引期间对数据进行排序的排序缓冲区的大小。指定的大小定义了读入内存进行内部排序然后写入磁盘的数据量。这个过程被称为“ 运行 ”。在合并阶段,读入并合并指定大小的缓冲区对。设置越大,运行和合并越少。
此排序区域仅用于创建索引期间的合并排序,而不用于以后的索引维护操作。索引创建完成后缓冲区将被释放。
此选项的值还控制在线DDL期间临时日志文件被扩展以记录并发DML的数量 操作。
在此设置可配置之前,该大小被硬编码为1048576字节(1MB),这仍然是默认设置。
在创建索引的语句ALTER TABLE或
CREATE TABLE语句中,分配了3个缓冲区,每个缓冲区的大小均由此选项定义。此外,辅助指针被分配给排序缓冲区中的行,以便排序可以在指针上运行(而不是在排序操作期间移动行)。
对于典型的排序操作,可以使用像这样的公式来估计内存消耗:
(6 / * FTS_NUM_AUX_INDEX * / *(3 * @@ global.innodb_sort_buffer_size) + 2 * number_of_partitions * number_of_secondary_indexes_created *(@@ global.innodb_sort_buffer_size / dict_index_get_min_size(index)* /) * 8 / * 64位sizeof * buf->元组* /“)
@@global.innodb_sort_buffer_size/dict_index_get_min_size(index)
表示持有的最大元组。2 *
(@@global.innodb_sort_buffer_size/*dict_index_get_min_size(index)*/)
* 8 /*64-bit size of *buf->tuples*/指示分配的辅助指针。
对于32位,乘以4而不是8。
对于全文索引的并行排序,乘以
innodb_ft_sort_pll_degree
设置:
(6 / * FTS_NUM_AUX_INDEX * / * @@ global.innodb_ft_sort_pll_degree)
| 属性 | 值 |
|---|---|
| 命令行格式 | --innodb-spin-wait-delay=# |
| 系统变量 | innodb_spin_wait_delay |
| 范围 | 全球 |
| 动态 | 是 |
| 类型(64位平台) | 整数 |
| 类型(32位平台) | 整数 |
| 默认(64位平台) | 6 |
| 默认(32位平台) | 6 |
| 最低(64位平台) | 0 |
| 最低(32位平台) | 0 |
| 最大(64位平台) | 2**64-1 |
| 最大(32位平台) | 2**32-1 |
自旋锁定 轮询之间的最大延迟时间 。该机制的低级实现取决于硬件和操作系统的组合,因此延迟不对应于固定的时间间隔。有关更多信息,请参见 第14.6.10节“配置旋转锁定轮询”。
| 属性 | 值 |
|---|---|
| 命令行格式 | --innodb-stats-auto-recalc=# |
| 系统变量 | innodb_stats_auto_recalc |
| 范围 | 全球 |
| 动态 | 是 |
| 类型 | 布尔 |
| 默认 | ON |
导致表格中的数据发生实质性更改后InnoDB自动重新计算
持久性统计信息。阈值是表中行的10%。此设置适用于innodb_stats_persistent
启用该选项时创建的表格
。自动统计重新计算也可以通过STATS_PERSISTENT=1在a
CREATE TABLE或
ALTER TABLE语句中指定进行配置
。用于生成统计数据的采样数据量由innodb_stats_persistent_sample_pages
配置选项控制
。
有关更多信息,请参见 第14.6.12.1节“配置持久优化器统计参数”。
innodb_stats_include_delete_marked
| 属性 | 值 |
|---|---|
| 命令行格式 | --innodb-stats-include-delete-marked=# |
| 介绍 | 5.7.17 |
| 系统变量 | innodb_stats_include_delete_marked |
| 范围 | 全球 |
| 动态 | 是 |
| 类型 | 布尔 |
| 默认 | OFF |
默认情况下,InnoDB在计算统计信息时读取未提交的数据。如果未提交的事务从表中删除行,则
InnoDB排除在计算行估计和索引统计信息时删除标记的记录,这可能会导致针对在表上操作的其他事务的非最佳执行计划使用事务隔离级别以外的
READ UNCOMMITTED。为了避免这种情况,
innodb_stats_include_delete_marked
可以启用它来确保InnoDB
在计算持久性优化器统计信息时包含删除标记的记录。
当
innodb_stats_include_delete_marked
启用时,ANALYZE TABLE
重新计算统计数据时,会考虑删除标记的记录。
innodb_stats_include_delete_marked
是影响所有InnoDB
表的全局设置。它仅适用于持久性优化器统计信息。
有关相关信息,请参见 第14.6.12.1节“配置持久优化器统计参数”。
| 属性 | 值 |
|---|---|
| 命令行格式 | --innodb-stats-method=name |
| 系统变量 | innodb_stats_method |
| 范围 | 全球 |
| 动态 | 是 |
| 类型 | 列举 |
| 默认 | nulls_equal |
| 有效值 |
|
NULL在收集
有关表格索引值分布的统计信息
时
,服务器如何处理值InnoDB。允许值是
nulls_equal,
nulls_unequal和
nulls_ignored。因为
nulls_equal,所有的NULL
索引值都被认为是相等的,并形成一个大小等于NULL值数量的单个值组
。因为
nulls_unequal,NULL
值被认为是不相等的,并且每个
NULL值形成大小为1的不同值组。对于nulls_ignored,
NULL值被忽略。
用于生成表统计信息的方法会影响优化程序如何为查询执行选择索引,如第8.3.7节“InnoDB和MyISAM索引统计信息收集”中所述。
| 属性 | 值 |
|---|---|
| 命令行格式 | --innodb-stats-on-metadata |
| 系统变量 | innodb_stats_on_metadata |
| 范围 | 全球 |
| 动态 | 是 |
| 类型 | 布尔 |
| 默认 | OFF |
此选项仅适用于将优化器
统计信息配置为非持久性的情况。优化器统计信息在innodb_stats_persistent禁用时或者在创建或更改单个表
时不会保留到磁盘
STATS_PERSISTENT=0。有关更多信息,请参见第14.6.12.2节“配置非持久性优化器统计参数”。
当innodb_stats_on_metadata启用时,
InnoDB将更新的非持久性
的统计数据时,元数据语句,如SHOW TABLE
STATUS访问时或
INFORMATION_SCHEMA.TABLES或
INFORMATION_SCHEMA.STATISTICS
表。(这些更新类似于发生的情况
ANALYZE TABLE。)禁用时,
InnoDB不会在这些操作期间更新统计信息。保持禁用设置可以提高具有大量表或索引的模式的访问速度。它还可以提高涉及表的查询
的执行计划的稳定性
InnoDB。
要更改设置,请发出声明,其中是or或(或
or )。更改设置需要特权并立即影响所有连接的操作。
SET GLOBAL
innodb_stats_on_metadata=modemodeONOFF10SUPER
| 属性 | 值 |
|---|---|
| 命令行格式 | --innodb-stats-persistent=setting |
| 系统变量 | innodb_stats_persistent |
| 范围 | 全球 |
| 动态 | 是 |
| 类型 | 布尔 |
| 默认 | ON |
| 有效值 |
|
指定是否将InnoDB索引统计信息保存到磁盘。否则,可能会频繁重新计算统计信息,这可能会导致查询执行计划发生变化
。创建表时,此设置与每个表一起存储。您可以设置
innodb_stats_persistent在全球范围内创建表之前,或使用
STATS_PERSISTENT的条款
CREATE TABLE和
ALTER TABLE语句覆盖系统级设置并配置各个表的持久性统计信息。
有关更多信息,请参见 第14.6.12.1节“配置持久优化器统计参数”。
innodb_stats_persistent_sample_pages
| 属性 | 值 |
|---|---|
| 命令行格式 | --innodb-stats-persistent-sample-pages=# |
| 系统变量 | innodb_stats_persistent_sample_pages |
| 范围 | 全球 |
| 动态 | 是 |
| 类型 | 整数 |
| 默认 | 20 |
估计索引列的基数和其他
统计数据时要抽样
的索引页数,例如由
。增加该值会提高索引统计信息的准确性,从而可以提高查询执行计划的执行过程中,在增加的I / O的费用
为表。有关更多信息,请参见第14.6.12.1节“配置持久优化器统计参数”。
ANALYZE TABLEANALYZE TABLEInnoDB
设置较高值
innodb_stats_persistent_sample_pages
可能会导致ANALYZE
TABLE执行时间过长。要估计访问的数据库页数ANALYZE
TABLE,请参见
第14.6.12.3节“估计InnoDB表的ANALYZE TABLE复杂度”。
innodb_stats_persistent_sample_pages仅适用于
innodb_stats_persistent启用了表格的情况; 当
innodb_stats_persistent禁用时,则
innodb_stats_transient_sample_pages
应用。
| 属性 | 值 |
|---|---|
| 命令行格式 | --innodb-stats-sample-pages=# |
| 弃用 | 是 |
| 系统变量 | innodb_stats_sample_pages |
| 范围 | 全球 |
| 动态 | 是 |
| 类型 | 整数 |
| 默认 | 8 |
| 最低限度 | 1 |
| 最大 | 2**64-1 |
已过时。innodb_stats_transient_sample_pages
改为使用
。
innodb_stats_transient_sample_pages
| 属性 | 值 |
|---|---|
| 命令行格式 | --innodb-stats-transient-sample-pages=# |
| 系统变量 | innodb_stats_transient_sample_pages |
| 范围 | 全球 |
| 动态 | 是 |
| 类型 | 整数 |
| 默认 | 8 |
估计索引列的基数和其他
统计数据时要抽样
的索引页数,例如由
。默认值为8.增加值可以提高索引统计的准确性,这可以改进
查询执行计划,但会增加打开表或重新计算统计信息时的I / O。
有关更多信息,请参见
第14.6.12.2节“配置非持久性优化器统计参数”。
ANALYZE TABLEInnoDB
设置较高值
innodb_stats_transient_sample_pages可能会导致ANALYZE
TABLE执行时间过长。要估计访问的数据库页数ANALYZE
TABLE,请参见
第14.6.12.3节“估计InnoDB表的ANALYZE TABLE复杂度”。
innodb_stats_transient_sample_pages仅适用于
innodb_stats_persistent禁用表格的情况; 当
innodb_stats_persistent启用时,
innodb_stats_persistent_sample_pages
则应该被使用。代替
innodb_stats_sample_pages。有关更多信息,请参见
第14.6.12.2节“配置非持久性优化器统计参数”。
| 属性 | 值 |
|---|---|
| 命令行格式 | --innodb-status-output |
| 介绍 | 5.7.4 |
| 系统变量 | innodb_status_output |
| 范围 | 全球 |
| 动态 | 是 |
| 类型 | 布尔 |
| 默认 | OFF |
启用或禁用标准InnoDB监视器的定期输出
。也可以与锁定监视器一起使用
innodb_status_output_locks或禁用周期性输出
InnoDB。有关更多信息,请参见第14.17.2节“启用InnoDB监视器”。
| 属性 | 值 |
|---|---|
| 命令行格式 | --innodb-status-output-locks |
| 介绍 | 5.7.4 |
| 系统变量 | innodb_status_output_locks |
| 范围 | 全球 |
| 动态 | 是 |
| 类型 | 布尔 |
| 默认 | OFF |
启用或禁用InnoDB锁定监视器。当启用时,InnoDB锁定监视器打印SHOW ENGINE INNODB STATUS输出中的锁定以及打印到MySQL错误日志的周期性输出中的附加信息
。InnoDB锁定监视器的周期性输出将作为标准InnoDB
监视器输出的一部分进行打印。因此,标准InnoDB监视器必须启用InnoDB
锁定监视器才能定期将数据打印到MySQL错误日志中。有关更多信息,请参见
第14.17.2节“启用InnoDB监视器”。
| 属性 | 值 |
|---|---|
| 命令行格式 | --innodb-strict-mode=# |
| 系统变量 | innodb_strict_mode |
| 范围 | 全球,会议 |
| 动态 | 是 |
| 类型 | 布尔 |
| 默认(> = 5.7.7) | ON |
| 默认(<= 5.7.6) | OFF |
当innodb_strict_mode启用时,
InnoDB将返回错误,而不是警告了一定的条件。
严格模式有助于防范SQL中忽略的拼写错误和语法错误,或各种操作模式和SQL语句组合的其他意外后果。当
innodb_strict_mode启用时,
InnoDB提出了在某些情况下错误条件,而不是发出警告和处理指定的声明(也许无意的行为)。这与sql_modeMySQL中的类似
,它控制MySQL接受的SQL语法,并确定它是静默地忽略错误还是验证输入语法和数据值。
该innodb_strict_mode设置会影响语法错误的处理CREATE
TABLE,ALTER TABLE,
CREATE INDEX,和
OPTIMIZE TABLE语句。
innodb_strict_mode还可以进行记录大小检查,以便记录对于所选页面大小而言过大,从而确保INSERT或
UPDATE永不失败。
Oracle建议使
innodb_strict_mode用时
ROW_FORMAT和
KEY_BLOCK_SIZE条款中
CREATE TABLE,
ALTER TABLE和
CREATE INDEX语句。当
innodb_strict_mode被禁用,
InnoDB忽略了相互矛盾的条款且仅在消息日志警告创建表或索引。结果表可能具有与预期不同的特性,例如尝试创建压缩表时缺乏压缩支持。当
innodb_strict_mode启用时,这些问题产生的直接错误,并且不会创建表或索引。
您可以innodb_strict_mode在启动mysqld时或在MySQL
配置文件中启用或禁用
命令行。您也可以innodb_strict_mode在运行时使用该语句启用或禁用
,其中是或者。更改设置需要
特权并影响后续连接的所有客户端的操作。任何客户端都可以更改设置
,并且该设置仅影响该客户端。
SET [GLOBAL|SESSION]
innodb_strict_mode=modemodeONOFFGLOBALSUPERSESSIONinnodb_strict_mode
innodb_strict_mode不适用于一般的表空间。通用表空间的表空间管理规则是独立于,严格执行的
innodb_strict_mode。有关更多信息,请参见第13.1.19节“CREATE TABLESPACE Syntax”。
| 属性 | 值 |
|---|---|
| 命令行格式 | --innodb-support-xa |
| 弃用 | 5.7.10 |
| 系统变量 | innodb_support_xa |
| 范围 | 全球,会议 |
| 动态 | 是 |
| 类型 | 布尔 |
| 默认 | TRUE |
启用InnoDB两相支持在提交XA事务,导致了交易准备一个额外的磁盘刷新。XA机制在内部使用,对于其二进制日志处于打开状态且正在接受来自多个线程的数据更改的任何服务器而言都是必不可少的。如果禁用
innodb_support_xa,则事务可以以不同于实时数据库提交的顺序的方式写入二进制日志,当二进制日志在灾难恢复或复制从属服务器中重播时,可以生成不同的数据。不要禁用
innodb_support_xa 在复制主服务器上,除非您有一个不寻常的设置,只有一个线程可以更改数据。
innodb_support_xa已被弃用,并将在未来的MySQL版本中被删除。InnoDB
对于XA事务中的两阶段提交的支持始终从MySQL 5.7.10开始启用。禁用
innodb_support_xa不再是允许的,因为它会导致复制不安全并阻止与二进制日志组提交相关的性能提升。
| 属性 | 值 |
|---|---|
| 命令行格式 | --innodb-sync-array-size=# |
| 系统变量 | innodb_sync_array_size |
| 范围 | 全球 |
| 动态 | 没有 |
| 类型 | 整数 |
| 默认 | 1 |
| 最低限度 | 1 |
| 最大 | 1024 |
定义互斥/锁等待数组的大小。增加值会拆分用于协调线程的内部数据结构,以便在具有大量等待线程的工作负载中实现更高的并发性。这个设置必须在MySQL实例启动时配置,并且以后不能更改。对于经常产生大量等待线程(通常大于768)的工作负载,建议增加此值。
| 属性 | 值 |
|---|---|
| 命令行格式 | --innodb-sync-spin-loops=# |
| 系统变量 | innodb_sync_spin_loops |
| 范围 | 全球 |
| 动态 | 是 |
| 类型 | 整数 |
| 默认 | 30 |
| 最低限度 | 0 |
| 最大 | 4294967295 |
InnoDB在线程暂停之前
线程等待
互斥锁释放的次数。
| 属性 | 值 |
|---|---|
| 命令行格式 | --innodb-sync-debug=# |
| 介绍 | 5.7.8 |
| 系统变量 | innodb_sync_debug |
| 范围 | 全球 |
| 动态 | 没有 |
| 类型 | 布尔 |
| 默认 | OFF |
启用InnoDB
存储引擎的同步调试检查。该选项仅在使用CMake选项编译调试支持时可用
。
WITH_DEBUG
以前,启用InnoDB同步调试检查需要使用CMake选项启用调试同步功能。MySQL 5.7中引入了此配置选项后,此要求被删除。
ENABLE_DEBUG_SYNC
| 属性 | 值 |
|---|---|
| 命令行格式 | --innodb-table-locks |
| 系统变量 | innodb_table_locks |
| 范围 | 全球,会议 |
| 动态 | 是 |
| 类型 | 布尔 |
| 默认 | TRUE |
如果autocommit = 0,
InnoDB荣誉LOCK
TABLES; LOCK
TABLES ... WRITE直到所有其他线程将所有锁释放到表中后,MySQL才会返回。默认值
innodb_table_locks是1,这意味着LOCK TABLES
导致InnoDB在内部锁定表
autocommit = 0。
在MySQL 5.7中,
innodb_table_locks = 0对显式锁定的表没有任何影响
LOCK TABLES ...
WRITE。它对LOCK TABLES ...
WRITE隐式(例如通过触发器)或通过隐式读取或写入的表有效
LOCK TABLES
... READ。
相关信息请参见 第14.5节“InnoDB锁定和事务模型”。
| 属性 | 值 |
|---|---|
| 命令行格式 | --innodb-temp-data-file-path=file |
| 介绍 | 5.7.1 |
| 系统变量 | innodb_temp_data_file_path |
| 范围 | 全球 |
| 动态 | 没有 |
| 类型 | 串 |
| 默认 | ibtmp1:12M:autoextend |
定义InnoDB
临时表空间 数据文件的相对路径,名称,大小和属性
。如果您未指定值
innodb_temp_data_file_path,则缺省行为是ibtmp1在MySQL数据目录中创建一个稍大于12MB的自动扩展数据文件。
临时表空间数据文件规范的完整语法包括文件名,文件大小
autoextend和max
属性:
file_name:file_size[:autoextend [:max:max_file_size]]
临时表空间数据文件不能与另一个InnoDB数据文件具有相同的名称。任何创建临时表空间数据文件的无效或错误都被视为致命错误,并且服务器启动被拒绝。临时表空间具有动态生成的空间ID,在每次服务器重新启动时可以更改该空间ID。
文件大小通过追加指定KB,MB或GB(1024MB)
K,M或
G大小值。文件大小的总和必须略大于12MB。
单个文件的大小限制取决于您的操作系统。在支持大文件的操作系统上,您可以将文件大小设置为4GB以上。不支持将原始磁盘分区用于临时表空间数据文件。
该autoextend和max
属性只能用于将最后一个指定的数据文件中使用
innodb_temp_data_file_path
的设置。例如:
的[mysqld] innodb_temp_data_file_path = ibtmp1:50M; ibtmp2:12M:自动扩展:最大:500MB
如果您指定了该autoextend选项,那么
InnoDB扩展数据文件(如果它的空闲空间不足)。该autoextend增量是默认64MB。要修改增量,请更改
innodb_autoextend_increment
系统变量。
临时表空间数据文件的完整目录路径是通过连接由innodb_data_home_dir和
定义的路径形成的
innodb_temp_data_file_path。
临时表空间由所有非压缩InnoDB临时表共享
。压缩的临时表驻留在由tmpdir配置选项定义的临时文件目录中创建的每表文件表空间文件中。
在InnoDB以只读模式运行之前,请将其设置
innodb_temp_data_file_path为数据目录之外的位置。该路径必须与数据目录相关。例如:
--innodb_temp_data_file_path = .. / .. / .. / TMP / ibtmp1:12M:自动扩展
关于活动InnoDB临时表的元数据位于
INFORMATION_SCHEMA.INNODB_TEMP_TABLE_INFO。
有关相关信息,请参见 第14.4.12节“临时表空间”。
| 属性 | 值 |
|---|---|
| 命令行格式 | --innodb-tmpdir=path |
| 介绍 | 5.7.11 |
| 系统变量 | innodb_tmpdir |
| 范围 | 全球,会议 |
| 动态 | 是 |
| 类型 | 目录名称 |
| 默认 | NULL |
用于为在ALTER
TABLE重建表的联机操作期间创建的临时排序文件定义备用目录。
ALTER TABLE重建表的
联机操作还会在原始表的同一目录中创建一个
中间表文件。该
innodb_tmpdir选项不适用于中间表文件。
有效值是MySQL数据目录路径以外的任何目录路径。如果该值为NULL(默认值),临时文件将创建MySQL临时目录($TMPDIR在Unix上,%TEMP%
在Windows上或由--tmpdir配置选项指定的目录
)。如果指定了目录,则只有在innodb_tmpdir使用SET
语句配置
目录和权限时才会检查目录和权限的存在
。如果在目录字符串中提供符号链接,则符号链接将被解析并存储为绝对路径。路径不应超过512个字节。ALTER TABLE如果innodb_tmpdir设置为无效目录,在线
操作会报告错误。innodb_tmpdir覆盖MySQL tmpdir设置,但仅限在线ALTER TABLE
操作。
该FILE权限需要配置
innodb_tmpdir。
innodb_tmpdir引入
该选项是为了避免溢出位于tmpfs文件系统上的临时文件目录
。由于在ALTER TABLE重建表的联机操作期间创建大量临时排序文件,可能会发生此类溢出。
在复制环境中,innodb_tmpdir如果所有服务器具有相同的操作系统环境,则只考虑复制该
设置。否则,innodb_tmpdir在运行ALTER TABLE重建表的联机操作时,复制设置可能会导致复制失败
。如果服务器操作环境不同,建议您分别innodb_tmpdir在每台服务器上进行配置
。
有关更多信息,请参阅
InnoDB存储临时文件的位置。有关在线ALTER TABLE
操作的信息,请参见第14.13节“InnoDB和Online DDL”。
| 属性 | 值 |
|---|---|
| 命令行格式 | --innodb-thread-concurrency=# |
| 系统变量 | innodb_thread_concurrency |
| 范围 | 全球 |
| 动态 | 是 |
| 类型 | 整数 |
| 默认 | 0 |
| 最低限度 | 0 |
| 最大 | 1000 |
InnoDB试图将操作系统线程的数量同时保持在
InnoDB小于或等于此变量给定的限制(InnoDB使用操作系统线程处理用户事务)。一旦线程数达到此限制,其他线程将进入“ 先入先出 ”(FIFO)队列中的等待状态以供执行。等待锁的线程不计入并发执行线程的数量。
此变量的范围是0到1000.值0(默认值)被解释为无限并发(无并发检查)。禁用线程并发检查可以InnoDB根据需要创建尽可能多的线程。值0也禁用queries
inside InnoDB和queries in queue
counters在ROW OPERATIONS
第SHOW ENGINE INNODB STATUS
输出。
如果您的MySQL实例与其他应用程序共享CPU资源,或者您的工作负载或并发用户数量不断增加,请考虑设置此变量。正确的设置取决于工作负载,计算环境以及您正在运行的MySQL版本。您需要测试一系列值以确定提供最佳性能的设置。innodb_thread_concurrency是一个动态变量,它允许您在实时测试系统上尝试不同的设置。如果某个特定设置性能不佳,可以快速设置
innodb_thread_concurrency回0。
使用以下准则来帮助查找并保持适当的设置:
如果工作负载的并发用户线程数小于64,则设置
innodb_thread_concurrency=0。
如果您的工作负载始终很高或偶尔会出现高峰,请首先设置
innodb_thread_concurrency=128值,然后将值降至96,80,64等等,直到找到提供最佳性能的线程数。例如,假设您的系统通常有40到50个用户,但是周期性地增加到60,70甚至200.您发现80个并发用户的性能是稳定的,但开始显示回归超过这个数字。在这种情况下,您将设置
innodb_thread_concurrency=80避免影响性能。
如果您不想InnoDB为用户线程使用超过一定数量的vCPU(例如20个vCPU),请设置
innodb_thread_concurrency为该数字(或可能较低,具体取决于性能结果)。如果您的目标是将MySQL与其他应用程序隔离,您可以考虑将mysqld进程专门绑定
到vCPU。但请注意,如果mysqld进程不一直繁忙,则独占绑定可能会导致非最佳硬件使用情况
。在这种情况下,您可以将mysqld进程绑定
到vCPU,但也允许其他应用程序使用部分或全部vCPU。
从操作系统的角度来看,使用资源管理解决方案来管理应用程序之间共享CPU时间的方式可能优于绑定该
mysqld过程。例如,您可以分配90%的vCPU的时间给定的应用程序,而其他关键进程不运行,而当其他关键流程扩展该值回到40%的
运行。
innodb_thread_concurrency 由于系统内部和资源争用的增加,过高的值可能导致性能回归。
在某些情况下,最佳
innodb_thread_concurrency设置可能会小于vCPU的数量。
定期监控和分析您的系统。工作负载,用户数量或计算环境的变化可能需要您调整
innodb_thread_concurrency设置。
有关相关信息,请参见 第14.6.6节“为InnoDB配置线程并发”。
innodb_trx_purge_view_update_only_debug
| 属性 | 值 |
|---|---|
| 命令行格式 | --innodb-trx-purge-view-update-only-debug=# |
| 系统变量 | innodb_trx_purge_view_update_only_debug |
| 范围 | 全球 |
| 动态 | 是 |
| 类型 | 布尔 |
| 默认 | OFF |
暂停清除删除标记的记录,同时允许更新清除视图。此选项人为地创建一个清除视图更新但尚未执行清除的情况。该选项仅在使用CMake选项编译调试支持时可用
。
WITH_DEBUG
| 属性 | 值 |
|---|---|
| 命令行格式 | --innodb-trx-rseg-n-slots-debug=# |
| 系统变量 | innodb_trx_rseg_n_slots_debug |
| 范围 | 全球 |
| 动态 | 是 |
| 类型 | 整数 |
| 默认 | 0 |
| 最大 | 1024 |
设置一个调试标志,该标志限制
TRX_RSEG_N_SLOTS为trx_rsegf_undo_find_free查找撤消日志段的空闲槽的函数的给定值
。该选项仅在使用CMake选项编译调试支持时可用
。
WITH_DEBUG
| 属性 | 值 |
|---|---|
| 命令行格式 | --innodb-thread-sleep-delay=# |
| 系统变量 | innodb_thread_sleep_delay |
| 范围 | 全球 |
| 动态 | 是 |
| 类型(64位平台,<= 5.7.3) | 整数 |
| 类型(32位平台,<= 5.7.3) | 整数 |
| 类型(> = 5.7.4) | 整数 |
| 默认(64位平台,<= 5.7.3) | 10000 |
| 默认(32位平台,<= 5.7.3) | 10000 |
| 默认(> = 5.7.4) | 10000 |
| 最小(64位平台,<= 5.7.3) | 0 |
| 最小(32位平台,<= 5.7.3) | 0 |
| 最小(> = 5.7.4) | 0 |
| 最大(64位平台,<= 5.7.3) | 18446744073709551615 |
| 最大(32位平台,<= 5.7.3) | 4294967295 |
| 最大(> = 5.7.4) | 1000000 |
定义InnoDB线程在加入InnoDB队列之前的睡眠时间,以微秒为单位。默认值为10000.值为0将禁用睡眠。您可以将配置选项设置为
innodb_adaptive_max_sleep_delay
允许的最高值
innodb_thread_sleep_delay,并
根据当前的线程调度活动InnoDB自动调整
innodb_thread_sleep_delay向上或向下。这种动态调整有助于线程调度机制在系统轻载或接近满负载运行时顺利运行。
有关更多信息,请参见 第14.6.6节“为InnoDB配置线程并发”。
| 属性 | 值 |
|---|---|
| 命令行格式 | --innodb-undo-directory=dir_name |
| 系统变量 | innodb_undo_directory |
| 范围 | 全球 |
| 动态 | 没有 |
| 类型 | 目录名称 |
| 默认(<= 5.7.7) | . |
InnoDB创建撤消表空间
的路径。通常用于将撤消日志放置在不同的存储设备上。与innodb_rollback_segments和
一起使用
innodb_undo_tablespaces。
没有默认值(它是NULL)。如果未指定路径,则撤消表空间将在MySQL数据目录中创建,如定义的那样
datadir。
有关更多信息,请参见 部分14.7.7,“配置撤消表空间”。
| 属性 | 值 |
|---|---|
| 命令行格式 | --innodb-undo-log-truncate=# |
| 介绍 | 5.7.5 |
| 系统变量 | innodb_undo_log_truncate |
| 范围 | 全球 |
| 动态 | 是 |
| 类型(> = 5.7.5) | 布尔 |
| 默认(> = 5.7.5) | OFF |
启用时,撤消超过由其定义的阈值的表空间
innodb_max_undo_log_size被标记为截断。只有撤消表空间可以被截断。截断驻留在系统表空间中的撤消日志不受支持。要截断发生,必须至少有两个撤消表空间和两个配置为使用撤消表空间的重做启用撤消日志。这意味着
innodb_undo_tablespaces必须将其设置为等于或大于2 innodb_rollback_segments的值,并且
必须设置为等于或大于35的值。
的
innodb_purge_rseg_truncate_frequency
配置选项可用于加速撤消tablepaces的截断。
有关更多信息,请参见 第14.7.8节“截断撤消表空间”。
| 属性 | 值 |
|---|---|
| 命令行格式 | --innodb-undo-logs=# |
| 弃用 | 19年7月5日 |
| 系统变量 | innodb_undo_logs |
| 范围 | 全球 |
| 动态 | 是 |
| 类型 | 整数 |
| 默认 | 128 |
| 最低限度 | 1 |
| 最大 | 128 |
innodb_undo_logs 已弃用,将在未来版本中删除。
定义的数量
回退段
由使用InnoDB。该
innodb_undo_logs选项是别名
innodb_rollback_segments。有关更多信息,请参阅说明
innodb_rollback_segments。
| 属性 | 值 |
|---|---|
| 命令行格式 | --innodb-undo-tablespaces=# |
| 弃用 | 21年7月5日 |
| 系统变量 | innodb_undo_tablespaces |
| 范围 | 全球 |
| 动态 | 没有 |
| 类型 | 整数 |
| 默认 | 0 |
| 最低限度 | 0 |
| 最大(> = 5.7.8) | 95 |
| 最大值(<= 5.7.7) | 126 |
的数量撤消表空间由使用InnoDB。默认值是0。
innodb_undo_tablespaces 已弃用,将在未来版本中删除。
由于在长时间运行的事务中撤消日志可能变大,因此在多个表空间中使用撤消日志可减少任何一个表空间的最大大小。撤消表空间文件是在由innodb_undo_directory名称形式定义的位置中创建
的
,其中
是一系列表示空间ID的连续整数(包括前导零)。
undoNN
撤消表空间文件的初始大小取决于该
innodb_page_size值。对于默认的16k InnoDB页大小,初始撤消表空间文件大小为10MiB。对于4k,8k,32k和64k页大小,初始撤消表空间文件大小分别为7MiB,8MiB,20MiB和40MiB。
至少需要两个撤消表空间才能启用撤销日志的截断。请参见 第14.7.8节“截断撤消表空间”。
innodb_undo_tablespaces只能在初始化MySQL实例之前进行配置,之后不能更改。如果未指定值,则使用默认设置0初始化实例。尝试InnoDB使用比初始化MySQL实例时指定的更大数量的还原表空间重新启动会导致启动失败并显示错误,指出InnoDB未找到预期的值撤消表空间的数量。
如临时表撤消日志中所述,将128个回滚段中的32个保留用于临时表
。一个回滚段总是分配给系统表空间,这样可以为撤消表空间留下95个回滚段。这意味着
innodb_undo_tablespaces
最大限制是95。
有关更多信息,请参见 部分14.7.7,“配置撤消表空间”。
| 属性 | 值 |
|---|---|
| 命令行格式 | --innodb-use-native-aio=# |
| 系统变量 | innodb_use_native_aio |
| 范围 | 全球 |
| 动态 | 没有 |
| 类型 | 布尔 |
| 默认 | ON |
指定是否使用Linux异步I / O子系统。此变量仅适用于Linux系统,并且在服务器运行时无法更改。通常,您不需要配置此选项,因为它默认情况下处于启用状态。
Linux系统上提供了Windows系统上
的异步I / O功能InnoDB。(其他类Unix系统继续使用同步I / O调用。)此功能提高了大量I / O绑定系统的可伸缩性,这些系统通常会在SHOW ENGINE INNODB STATUS\G输出中显示许多待执行的读取/写入操作
。
运行大量InnoDBI / O线程,特别是在同一台服务器上运行多个此类实例时,可能会超出Linux系统的容量限制。在这种情况下,您可能会收到以下错误:
EAGAIN:指定的maxevents超出用户对可用事件的限制。
您通常可以通过写入更高的限制来解决此错误/proc/sys/fs/aio-max-nr。
但是,如果操作系统中的异步I / O子系统的问题阻止InnoDB启动,则可以使用启动服务器
innodb_use_native_aio=0。如果InnoDB检测到潜在问题(例如tmpdir位置,
tmpfs文件系统和不支持AIO的Linux内核的组合),则也可能在启动期间自动禁用此选项
tmpfs。
有关更多信息,请参见 第14.6.8节“在Linux上使用异步I / O”。
| 属性 | 值 |
|---|---|
| 命令行格式 | --innodb-use-sys-malloc=# |
| 弃用 | 是(在5.7.4中删除) |
| 系统变量 | innodb_use_sys_malloc |
| 范围 | 全球 |
| 动态 | 没有 |
| 类型 | 布尔 |
| 默认 | ON |
启用操作系统内存分配器。如果禁用,则
InnoDB使用其自己的分配器。默认值是ON。有关更多信息,请参见
第14.6.4节“为InnoDB配置内存分配器”。
innodb_use_sys_malloc 在MySQL 5.7中被删除。
该InnoDB版本号。在MySQL 5.7中,单独的版本编号
InnoDB不适用,并且此值version与服务器的编号相同。
| 属性 | 值 |
|---|---|
| 命令行格式 | --innodb-write-io-threads=# |
| 系统变量 | innodb_write_io_threads |
| 范围 | 全球 |
| 动态 | 没有 |
| 类型 | 整数 |
| 默认 | 4 |
| 最低限度 | 1 |
| 最大 | 64 |
用于写入操作的I / O线程数
InnoDB。缺省值是4.它与读取线程的对应关系是
innodb_read_io_threads。有关更多信息,请参见
第14.6.7节“配置背景InnoDB I / O线程数”。有关通用I / O优化建议,请参见
第8.5.8节“优化InnoDB磁盘I / O”。
在Linux系统上运行多个MySQL服务器(通常超过12)与默认设置
innodb_read_io_threads,
innodb_write_io_threads以及Linux的
aio-max-nr设置可以超过系统限制。理想情况下,增加aio-max-nr
设置; 作为一种解决方法,您可以减少一个或两个MySQL配置选项的设置。
还要考虑
sync_binlog控制二进制日志同步到磁盘的值。
有关通用I / O优化建议,请参见 第8.5.8节“优化InnoDB磁盘I / O”。
本节提供InnoDB
INFORMATION_SCHEMA表格的信息和使用示例
。
InnoDB INFORMATION_SCHEMA
表提供了有关InnoDB存储引擎各个方面的元数据,状态信息和统计信息。您可以InnoDB
INFORMATION_SCHEMA通过SHOW TABLES在INFORMATION_SCHEMA数据库上发布声明
来查看表
的列表:
MySQL的> SHOW TABLES FROM INFORMATION_SCHEMA LIKE 'INNODB%';
有关表格定义,请参见第24.31节“InnoDB INFORMATION_SCHEMA表格”。有关MySQL
INFORMATION_SCHEMA数据库的一般信息,请参阅
第24章INFORMATION_SCHEMA表。
有两对InnoDB
INFORMATION_SCHEMA关于压缩的表格可以提供对整体压缩效果如何的深入了解:
INNODB_CMP并
INNODB_CMP_RESET
包含有关压缩操作数量和执行压缩所花费时间的信息。
INNODB_CMPMEM并
INNODB_CMP_RESET
包含有关内存分配用于压缩的方式的信息。
在INNODB_CMP与
INNODB_CMP_RESET
表包含与压缩表执行的操作,这被描述的状态信息
14.9节,“InnoDB的表和页压缩”。该
PAGE_SIZE列报告压缩的
页面大小。
这两个表具有相同的内容,但读取
INNODB_CMP_RESET
重置压缩和解压缩操作的统计信息。例如,如果您INNODB_CMP_RESET
每隔60分钟输出
一次,则会看到每个小时的统计数据。如果您监控INNODB_CMP(确保永不读取
INNODB_CMP_RESET)的输出
,您会看到InnoDB启动以来的累计统计数据。
有关表定义,请参见 第24.31.4节“INFORMATION_SCHEMA INNODB_CMP和INNODB_CMP_RESET表”。
在INNODB_CMPMEM与
INNODB_CMPMEM_RESET
表包含驻留在缓冲池中压缩页的状态信息。请参阅
第14.9节“InnoDB表和页面压缩”以获取有关压缩表和缓冲池使用的更多信息。在
INNODB_CMP和
INNODB_CMP_RESET
表格应提供关于压缩的更多有用的统计数据。
InnoDB使用
好友分配器
系统来管理分配给各种大小页面的内存
,从1KB到16KB。这里描述的两个表中的每一行对应于单个页面大小。
在INNODB_CMPMEM与
INNODB_CMPMEM_RESET
表的内容相同,但是从阅读
INNODB_CMPMEM_RESET
重置迁址操作的统计信息。例如,如果每隔60分钟存档一次输出
INNODB_CMPMEM_RESET,则会显示小时统计。如果您从不读取
INNODB_CMPMEM_RESET
和监控输出
INNODB_CMPMEM,它会显示自InnoDB
启动以来的累计统计数据。
有关表定义,请参见 第24.31.5节“INFORMATION_SCHEMA INNODB_CMPMEM和INNODB_CMPMEM_RESET表”。
例14.1使用压缩信息模式表
以下是从包含压缩表(见数据库样本输出第14.9节,“InnoDB的表和页压缩”,
INNODB_CMP,
INNODB_CMP_PER_INDEX,和
INNODB_CMPMEM)。
下表显示INFORMATION_SCHEMA.INNODB_CMP
了轻工作负载下的内容
。缓冲池包含的唯一压缩页面大小为8K。压缩或解压缩的网页已经消耗不到,因为统计数字重置时间的第二,因为列COMPRESS_TIME和
UNCOMPRESS_TIME为零。
| 页面大小 | 压缩操作 | 压缩操作正常 | 压缩时间 | 解压缩操作 | 解压缩时间 |
|---|---|---|---|---|---|
| 1024 | 0 | 0 | 0 | 0 | 0 |
| 2048 | 0 | 0 | 0 | 0 | 0 |
| 4096 | 0 | 0 | 0 | 0 | 0 |
| 8192 | 1048 | 921 | 0 | 61 | 0 |
| 16384 | 0 | 0 | 0 | 0 | 0 |
据说INNODB_CMPMEM,缓冲池中有6169个压缩的8KB页面
。唯一的其他分配的块大小是64个字节。最小的
PAGE_SIZEin
INNODB_CMPMEM用于缓冲池中没有未压缩页面的压缩页面的块描述符。我们看到有5910个这样的页面。间接地,我们看到259(6169-5910)压缩页面也以非压缩形式存在于缓冲池中。
下表显示INFORMATION_SCHEMA.INNODB_CMPMEM
了轻工作负载下的内容
。由于压缩页面的内存分配器碎片,某些内存不可用:
SUM(PAGE_SIZE*PAGES_FREE)=6784。这是因为小内存分配请求是通过使用伙伴分配系统从主缓冲池分配的16K块开始分割更大的块来实现的。碎片是这么低,因为一些分配的块已经被重新定位(复制)以形成更大的相邻空闲块。这种SUM(PAGE_SIZE*RELOCATION_OPS)字节的复制
消耗不到一秒钟
(SUM(RELOCATION_TIME)=0)。
使用三个InnoDB
INFORMATION_SCHEMA表可以监视事务并诊断潜在的锁定问题:
INNODB_TRX:包含有关当前内部执行的每个事务的信息
InnoDB,包括事务状态(例如,是否正在运行或正在等待锁),事务何时开始以及事务正在执行的特定SQL语句。
INNODB_LOCKS:在InnoDB的每个事务正在等待另一事务释放锁(INNODB_TRX.TRX_STATE是LOCK
WAIT)由恰好一个阻挡锁请求阻止。该阻塞锁请求是针对另一个事务处于不兼容模式下的行或表锁。阻止事务的锁始终保持与请求的锁定模式不兼容的模式(读取与写入,共享与独占)。在其他事务提交或回滚之前,被阻止的事务不能继续,从而释放所请求的锁。对于每个被阻止的事务,都
INNODB_LOCKS包含一行描述事务请求的每个锁以及它正在等待的锁。
INNODB_LOCKS还包含一个行的每个阻塞另一个事务,锁定不管这持有锁的事务的状态(INNODB_TRX.TRX_STATE是
RUNNING,LOCK WAIT,
ROLLING BACK或
COMMITTING)。
INNODB_LOCK_WAITS:该表指示哪些事务正在等待给定的锁,或者给定事务正在等待哪个锁。此表包含每个被阻止的事务的一个或多个行,指示它所请求的锁和任何阻止该请求的锁。该
REQUESTED_LOCK_ID值指的是事务请求的锁,并且该
BLOCKING_LOCK_ID值指的是阻止第一个事务继续进行的锁(由另一个事务持有)。对于任何给定的被阻止事务,所有行都
INNODB_LOCK_WAITS具有相同的值REQUESTED_LOCK_ID和不同的值BLOCKING_LOCK_ID。
有关上述表格的更多信息,请参见 第24.31.27节“INFORMATION_SCHEMA INNODB_TRX表”, 第24.31.13节“INFORMATION_SCHEMA INNODB_LOCKS表”和 第24.31.14节“INFORMATION_SCHEMA INNODB_LOCK_WAITS表”。
识别另一个事务块有时很有用。包含有关InnoDB事务和数据锁定信息的表
使您能够确定哪个事务正在等待另一个事务以及正在请求哪个资源。(有关这些表的说明,请参见
第14.15.2节“InnoDB INFORMATION_SCHEMA事务和锁定信息”。)
假设三个会话正在同时运行。每个会话对应一个MySQL线程,并且一个接一个地执行一个事务。当这些会议发布以下声明时,请考虑系统的状态,但是还没有人提交它的事务:
会议A:
开始; 选择一个FROM t FOR UPDATE; SELECT SLEEP(100);
会议B:
SELECT b FROM t FOR UPDATE;
会议C:
SELECT c FROM t FOR UPDATE;
在这种情况下,请使用以下查询来查看哪些事务正在等待以及哪些事务阻止它们:
选择 r.trx_id waiting_trx_id, r.trx_mysql_thread_id waiting_thread, r.trx_query waiting_query, b.trx_id blocking_trx_id, b.trx_mysql_thread_id blocking_thread, b.trx_query blocking_query FROM information_schema.innodb_lock_waits w INNER JOIN information_schema.innodb_trx b ON b.trx_id = w.blocking_trx_id INNER JOIN information_schema.innodb_trx r ON r.trx_id = w.requesting_trx_id;
或者更简单地说,使用sys模式
innodb_lock_waits视图:
选择 waiting_trx_id, waiting_pid, waiting_query, blocking_trx_id, blocking_pid, blocking_query FROM sys.innodb_lock_waits;
如果阻塞查询报告了NULL值,请参阅 在发布会话变为空闲后识别阻塞查询。
| 等待trx id | 等待线程 | 等待查询 | 阻止trx id | 阻塞线程 | 阻止查询 |
|---|---|---|---|---|---|
A4 |
6 |
SELECT b FROM t FOR UPDATE |
A3 |
5 |
SELECT SLEEP(100) |
A5 |
7 |
SELECT c FROM t FOR UPDATE |
A3 |
5 |
SELECT SLEEP(100) |
A5 |
7 |
SELECT c FROM t FOR UPDATE |
A4 |
6 |
SELECT b FROM t FOR UPDATE |
在上表中,您可以通过“ 等待查询 ”或“ 阻止查询 ” 列来识别会话 。如你看到的:
会话B(trx id A4,线程
6)和会话C(trx id
A5,线程7)都等待会话A(trx id A3,线程5)。
会话C正在等待会话B以及会话A.
你可以看到表中的基础数据
INNODB_TRX,
INNODB_LOCKS以及
INNODB_LOCK_WAITS。
下表显示了一些示例内容
INFORMATION_SCHEMA.INNODB_TRX。
| trx id | trx状态 | trx开始了 | trx请求的锁定ID | trx等待开始 | trx重量 | trx mysql线程ID | trx查询 |
|---|---|---|---|---|---|---|---|
A3 |
RUNNING |
2008-01-15 16:44:54 |
NULL |
NULL |
2 |
5 |
SELECT SLEEP(100) |
A4 |
LOCK WAIT |
2008-01-15 16:45:09 |
A4:1:3:2 |
2008-01-15 16:45:09 |
2 |
6 |
SELECT b FROM t FOR UPDATE |
A5 |
LOCK WAIT |
2008-01-15 16:45:14 |
A5:1:3:2 |
2008-01-15 16:45:14 |
2 |
7 |
SELECT c FROM t FOR UPDATE |
下表显示了一些示例内容
INFORMATION_SCHEMA.INNODB_LOCKS。
| 锁定ID | 锁定trx id | 锁定模式 | 锁定类型 | 锁表 | 锁定索引 | 锁定数据 |
|---|---|---|---|---|---|---|
A3:1:3:2 |
A3 |
X |
RECORD |
test.t |
PRIMARY |
0x0200 |
A4:1:3:2 |
A4 |
X |
RECORD |
test.t |
PRIMARY |
0x0200 |
A5:1:3:2 |
A5 |
X |
RECORD |
test.t |
PRIMARY |
0x0200 |
下表显示了一些示例内容
INFORMATION_SCHEMA.INNODB_LOCK_WAITS。
在识别阻塞事务时,如果发出查询的会话已变为空闲,则会为阻塞查询报告NULL值。在这种情况下,请使用以下步骤确定阻止查询:
识别阻塞事务的进程列表ID。在sys.innodb_lock_waits
表中,阻塞事务的流程列表ID是blocking_pid值。
使用blocking_pid查询MySQL性能模式threads
表来确定THREAD_ID阻塞事务。例如,如果
blocking_pid是6,请发出以下查询:
SELECT THREAD_ID FROM performance_schema.threads WHERE PROCESSLIST_ID = 6;
使用THREAD_ID查询性能模式
events_statements_current
表来确定线程执行的最后一个查询。例如,如果THREAD_ID是28,请发出以下查询:
SELECT THREAD_ID,SQL_TEXT FROM performance_schema.events_statements_current WHERE THREAD_ID = 28 \ G
如果线程执行的最后一个查询没有足够的信息来确定为什么锁持有,您可以查询Performance Schema
events_statements_history
表以查看线程执行的最后10条语句。
SELECT THREAD_ID,SQL_TEXT FROM performance_schema.events_statements_history WHERE THREAD_ID = 28 ORDER BY EVENT_ID;
有时将内部InnoDB锁定信息与MySQL维护的会话级信息关联起来会很有用
。例如,对于给定的InnoDB
事务标识,您可能想知道对应的MySQL会话标识和可能持有锁的会话的名称,从而阻止其他事务。
以下来自INFORMATION_SCHEMA表格的输出来自
一个稍微加载的系统。可以看出,有几个交易正在运行。
以下INNODB_LOCKS和
INNODB_LOCK_WAITS表格显示:
在INFORMATION_SCHEMA
PROCESSLIST和
INNODB_TRX表中显示的查询之间可能存在不一致
。有关说明,请参见
第14.15.2.3节“InnoDB事务和锁定信息的持久性和一致性”。
下表显示了INFORMATION_SCHEMA.PROCESSLIST
运行繁重工作负载的系统
的内容
。
| ID | 用户 | 主办 | D B | 命令 | 时间 | 州 | 信息 |
|---|---|---|---|---|---|---|---|
384 |
root |
localhost |
test |
Query |
10 |
update |
INSERT INTO t2 VALUES … |
257 |
root |
localhost |
test |
Query |
3 |
update |
INSERT INTO t2 VALUES … |
130 |
root |
localhost |
test |
Query |
0 |
update |
INSERT INTO t2 VALUES … |
61 |
root |
localhost |
test |
Query |
1 |
update |
INSERT INTO t2 VALUES … |
8 |
root |
localhost |
test |
Query |
1 |
update |
INSERT INTO t2 VALUES … |
4 |
root |
localhost |
test |
Query |
0 |
preparing |
SELECT * FROM PROCESSLIST |
2 |
root |
localhost |
test |
Sleep |
566 |
|
NULL |
下表显示了INFORMATION_SCHEMA.INNODB_TRX运行繁重工作负载的系统
的内容
。
| trx id | trx状态 | trx开始了 | trx请求的锁定ID | trx等待开始 | trx重量 | trx mysql线程ID | trx查询 |
|---|---|---|---|---|---|---|---|
77F |
LOCK WAIT |
2008-01-15 13:10:16 |
77F |
2008-01-15 13:10:16 |
1 |
876 |
INSERT INTO t09 (D, B, C) VALUES … |
77E |
LOCK WAIT |
2008-01-15 13:10:16 |
77E |
2008-01-15 13:10:16 |
1 |
875 |
INSERT INTO t09 (D, B, C) VALUES … |
77D |
LOCK WAIT |
2008-01-15 13:10:16 |
77D |
2008-01-15 13:10:16 |
1 |
874 |
INSERT INTO t09 (D, B, C) VALUES … |
77B |
LOCK WAIT |
2008-01-15 13:10:16 |
77B:733:12:1 |
2008-01-15 13:10:16 |
4 |
873 |
INSERT INTO t09 (D, B, C) VALUES … |
77A |
RUNNING |
2008-01-15 13:10:16 |
NULL |
NULL |
4 |
872 |
SELECT b, c FROM t09 WHERE … |
E56 |
LOCK WAIT |
2008-01-15 13:10:06 |
E56:743:6:2 |
2008-01-15 13:10:06 |
5 |
384 |
INSERT INTO t2 VALUES … |
E55 |
LOCK WAIT |
2008-01-15 13:10:06 |
E55:743:38:2 |
2008-01-15 13:10:13 |
965 |
257 |
INSERT INTO t2 VALUES … |
19C |
RUNNING |
2008-01-15 13:09:10 |
NULL |
NULL |
2900 |
130 |
INSERT INTO t2 VALUES … |
E15 |
RUNNING |
2008-01-15 13:08:59 |
NULL |
NULL |
5395 |
61 |
INSERT INTO t2 VALUES … |
51D |
RUNNING |
2008-01-15 13:08:47 |
NULL |
NULL |
9807 |
8 |
INSERT INTO t2 VALUES … |
下表显示了INFORMATION_SCHEMA.INNODB_LOCK_WAITS
运行繁重工作负载的系统
的内容
。
| 请求trx id | 请求的锁定ID | 阻止trx id | 阻止锁定ID |
|---|---|---|---|
77F |
77F:806 |
77E |
77E:806 |
77F |
77F:806 |
77D |
77D:806 |
77F |
77F:806 |
77B |
77B:806 |
77E |
77E:806 |
77D |
77D:806 |
77E |
77E:806 |
77B |
77B:806 |
77D |
77D:806 |
77B |
77B:806 |
77B |
77B:733:12:1 |
77A |
77A:733:12:1 |
E56 |
E56:743:6:2 |
E55 |
E55:743:6:2 |
E55 |
E55:743:38:2 |
19C |
19C:743:38:2 |
下表显示了INFORMATION_SCHEMA.INNODB_LOCKS
运行繁重工作负载的系统
的内容
。
| 锁定ID | 锁定trx id | 锁定模式 | 锁定类型 | 锁表 | 锁定索引 | 锁定数据 |
|---|---|---|---|---|---|---|
77F:806 |
77F |
AUTO_INC |
TABLE |
test.t09 |
NULL |
NULL |
77E:806 |
77E |
AUTO_INC |
TABLE |
test.t09 |
NULL |
NULL |
77D:806 |
77D |
AUTO_INC |
TABLE |
test.t09 |
NULL |
NULL |
77B:806 |
77B |
AUTO_INC |
TABLE |
test.t09 |
NULL |
NULL |
77B:733:12:1 |
77B |
X |
RECORD |
test.t09 |
PRIMARY |
supremum pseudo-record |
77A:733:12:1 |
77A |
X |
RECORD |
test.t09 |
PRIMARY |
supremum pseudo-record |
E56:743:6:2 |
E56 |
S |
RECORD |
test.t2 |
PRIMARY |
0, 0 |
E55:743:6:2 |
E55 |
X |
RECORD |
test.t2 |
PRIMARY |
0, 0 |
E55:743:38:2 |
E55 |
S |
RECORD |
test.t2 |
PRIMARY |
1922, 1922 |
19C:743:38:2 |
19C |
X |
RECORD |
test.t2 |
PRIMARY |
1922, 1922 |
当一个事务在一个表中更新了一行,或将其锁定
SELECT FOR UPDATE,InnoDB
建立在该行锁的列表或队列。同样,
InnoDB维护表级锁的列表。如果第二个事务想要以不兼容的模式更新行或锁定已被先前事务锁定的表,InnoDB请将该行的锁定请求添加到相应的队列。对于事务获取的锁,必须删除以前输入到该行或表的锁定队列中的所有不兼容的锁请求(发生在持有或请求这些锁的事务提交或回滚时)。
对于不同的行或表,事务可能有任意数量的锁请求。在任何特定时间,交易都可以请求由另一个交易持有的锁,在这种情况下,该交易被该另一个交易阻止。请求事务必须等待持有阻塞锁的事务提交或回滚。如果一个事务没有等待一个锁,它就处于一个RUNNING状态。如果一个事务正在等待一个锁,它就处于一个LOCK WAIT
状态。(该INFORMATION_SCHEMA
INNODB_TRX表指示事务状态值。)
该INNODB_LOCKS表为每个LOCK WAIT事务保存一行或多行,指示阻止其进展的任何锁定请求。该表还包含一行,用于描述给定行或表的挂起队列中的每个锁。该
INNODB_LOCK_WAITS表显示事务已保存的哪些锁定正在阻止其他事务请求的锁定。
由交易和锁定表公开的数据(INNODB_TRX,
INNODB_LOCKS,和
INNODB_LOCK_WAITS)表示窥探到快速变化的数据。这不像用户表,其中数据仅在应用程序启动的更新发生时才更改。基础数据是内部系统管理的数据,并且可以快速更改。
出于性能方面的考虑,为了尽量减少事务和锁定表之间InnoDB误入连接的可能性,只要SELECT发布任何表,
就将所需的事务和锁定信息收集到中间缓冲区中
。只有在自上次读取缓冲区起超过0.1秒时,才会刷新此缓冲区。填充这三个表所需的数据是以原子方式一致地获取的,并保存在此全局内部缓冲区中,形成一个时间点
“ 快照 ”。如果在0.1秒内发生多次表访问(因为当MySQL处理这些表之间的连接时它们几乎肯定会发生),则使用相同的快照来满足查询。
当您在单个查询中将这些表中的任何一个连接在一起时,会返回正确的结果,因为三个表的数据来自同一个快照。因为缓冲区不会被任何这些表的每个查询刷新,所以如果您在十分之一秒内针对这些表发出单独的查询,则查询结果与查询相同。另一方面,对于相同或不同表格发出的两次不同查询,可能会看到不同的结果,因为数据来自不同的快照。
由于InnoDB在收集事务和锁定数据时必须暂时停止,因此如果其他用户看到这些表的频繁查询会对性能产生负面影响。
由于这些表包含敏感信息(至少
INNODB_LOCKS.LOCK_DATA和
INNODB_TRX.TRX_QUERY),出于安全原因,只有具有该PROCESS权限的用户才可以SELECT从中获得。
如前所述,填充所述交易和锁定表(数据INNODB_TRX,
INNODB_LOCKS和
INNODB_LOCK_WAITS)被自动提取并保存到提供的中间缓冲器“ 点即时 ”快照。当从同一快照查询时,所有三个表中的数据都是一致的。但是,基础数据变化如此之快,以至于类似快速变化数据的类似瞥见可能不会同步。因此,在比较InnoDB事务中的数据和锁定表中的数据时应该小心PROCESSLIST。数据来自PROCESSLIST表不是来自与关于锁定和事务的数据相同的快照。即使您发出单个
SELECT(加入
INNODB_TRX和
PROCESSLIST例如),这些表的内容通常也不一致。
INNODB_TRX可能引用行中不存在PROCESSLIST或当前正在执行的SQL查询中显示的事务
INNODB_TRX.TRX_QUERY可能不同于在PROCESSLIST.INFO。
您可以提取有关InnoDB使用InnoDB
INFORMATION_SCHEMA系统表管理的模式对象的元数据
。这些信息来自InnoDB内部系统表(也称为InnoDB
数据字典),不能像常规InnoDB表一样直接查询
。传统上,您将使用第14.17节“InnoDB监视器”中的技术获取此类信息
,设置
InnoDB监视器并解析SHOW ENGINE INNODB
STATUS语句的输出
。该InnoDB
INFORMATION_SCHEMA表界面允许您使用SQL查询数据。
除了
INNODB_SYS_TABLESTATS没有相应内部系统表的系统表外,
InnoDB INFORMATION_SCHEMA
系统表中填充的数据直接从内部InnoDB系统表中读取,而不是从内存中缓存的元数据中读取
。
InnoDB INFORMATION_SCHEMA
系统表格包括下面列出的表格。
INNODB_SYS_DATAFILES并且
INNODB_SYS_TABLESPACES在MySQL 5.6.6中添加了对语句子句的支持,该语句允许在MySQL数据目录之外的位置创建按文件表的表
空间(文件)。
DATA
DIRECTORY='directory'CREATE TABLEInnoDB
.ibd
MySQL的> SHOW TABLES FROM INFORMATION_SCHEMA LIKE 'INNODB_SYS%';
+ -------------------------------------------- +
| Tables_in_information_schema(INNODB_SYS%)|
+ -------------------------------------------- +
| INNODB_SYS_DATAFILES |
| INNODB_SYS_TABLESTATS |
| INNODB_SYS_FOREIGN |
| INNODB_SYS_COLUMNS |
| INNODB_SYS_INDEXES |
| INNODB_SYS_FIELDS |
| INNODB_SYS_TABLESPACES |
| INNODB_SYS_FOREIGN_COLS |
| INNODB_SYS_TABLES |
+ -------------------------------------------- +
表格名称表示提供的数据类型:
INNODB_SYS_TABLES提供有关InnoDB表的元数据,等同SYS_TABLES于InnoDB数据字典中表中的信息。
INNODB_SYS_COLUMNS提供有关InnoDB表列的元数据,等同
SYS_COLUMNS于InnoDB数据字典中表中的
信息。
INNODB_SYS_INDEXES提供有关InnoDB索引的元数据,等同SYS_INDEXES于InnoDB数据字典中表中的信息。
INNODB_SYS_FIELDS提供有关InnoDB索引键列(字段)的元数据
,等同SYS_FIELDS于InnoDB数据字典中表中的
信息。
INNODB_SYS_TABLESTATS提供了有关InnoDB从内存数据结构派生的表的低级状态信息的视图
。没有相应的内部
InnoDB系统表。
INNODB_SYS_DATAFILES为InnoDB
文件每表和数据字典提供数据文件路径信息,相当于SYS_DATAFILES表中的InnoDB信息。
INNODB_SYS_TABLESPACES提供关于InnoDB每个表和一般表空间的元数据,等同
SYS_TABLESPACES于InnoDB数据字典中表中的
信息。
INNODB_SYS_FOREIGN提供有关在InnoDB表上定义的外键的元数据
,等同SYS_FOREIGN于InnoDB数据字典中表中的
信息。
INNODB_SYS_FOREIGN_COLS提供有关在表上定义的外键列的元数据
InnoDB,等同SYS_FOREIGN_COLS于InnoDB数据字典中表中的信息。
InnoDB INFORMATION_SCHEMA
系统表可通过领域,如连接在一起
TABLE_ID,INDEX_ID和
SPACE,让您轻松检索所有可用的数据,你想学习或监视的对象。
有关每个表的列的信息,
请参阅InnoDB
INFORMATION_SCHEMA文档。
例14.2 InnoDB INFORMATION_SCHEMA系统表
本示例使用一个t1带有单个索引(i1)的简单table()来演示在InnoDB
INFORMATION_SCHEMA系统表中找到的元数据的类型。
创建一个测试数据库和表格t1:
MySQL的>CREATE DATABASE test;MySQL的>USE test;MySQL的>CREATE TABLE t1 (col1 INT,col2 CHAR(10),col3 VARCHAR(10))ENGINE = InnoDB;MySQL的>CREATE INDEX i1 ON t1(col1);
创建表后t1,查询
INNODB_SYS_TABLES以找到元数据test/t1:
MySQL的> SELECT * FROM INFORMATION_SCHEMA.INNODB_SYS_TABLES WHERE NAME='test/t1' \G
*************************** 1. row ******************** *******
TABLE_ID:71
NAME:test / t1
FLAG:1
N_COLS:6
空间:57
FILE_FORMAT:羚羊
ROW_FORMAT:紧凑
ZIP_PAGE_SIZE:0
...
表格t1有
TABLE_ID71个FLAG字段。该
字段提供有关表格格式和存储特征的位级信息。有六列,其中三个是通过创建隐藏的列
InnoDB(DB_ROW_ID,
DB_TRX_ID,和
DB_ROLL_PTR)。表的ID
SPACE是57(值为0表示该表驻留在系统表空间中)。该
FILE_FORMAT是羚羊和
ROW_FORMAT紧凑。
ZIP_PAGE_SIZE仅适用于具有Compressed行格式的表格。
使用TABLE_ID来自的信息
INNODB_SYS_TABLES,查询
INNODB_SYS_COLUMNS表格以获取关于表格列的信息。
MySQL的> SELECT * FROM INFORMATION_SCHEMA.INNODB_SYS_COLUMNS where TABLE_ID = 71 \G
*************************** 1. row ******************** *******
TABLE_ID:71
名称:col1
POS:0
MTYPE:6
PRTYPE:1027
LEN:4
*************************** 2. row ******************** *******
TABLE_ID:71
名称:col2
POS:1
MTYPE:2
PRTYPE:524542
LEN:10
*************************** 3. row ******************** *******
TABLE_ID:71
名称:col3
POS:2
MTYPE:1
PRTYPE:524303
LEN:10
除了TABLE_ID和列之外
NAME,
INNODB_SYS_COLUMNS还提供了POS每列的序号位置()(从0开始并依次递增),列
MTYPE或“ 主类型 ”(6 = INT,2 = CHAR,1 = VARCHAR),PRTYPE
或“ 精确键入 “(代表MySQL数据类型,字符集代码和可空性的二进制值)和列长度(LEN)。
再次
使用这些TABLE_ID信息
INNODB_SYS_TABLES,查询INNODB_SYS_INDEXES有关与表关联的索引的信息
t1。
MySQL的> SELECT * FROM INFORMATION_SCHEMA.INNODB_SYS_INDEXES WHERE TABLE_ID = 71 \G
*************************** 1. row ******************** *******
INDEX_ID:111
名称:GEN_CLUST_INDEX
TABLE_ID:71
类型:1
N_FIELDS:0
PAGE_NO:3
空间:57
MERGE_THRESHOLD:50
*************************** 2. row ******************** *******
INDEX_ID:112
姓名:i1
TABLE_ID:71
类型:0
N_FIELDS:1
PAGE_NO:4
空间:57
MERGE_THRESHOLD:50
INNODB_SYS_INDEXES返回两个索引的数据。第一个索引是
GEN_CLUST_INDEX,InnoDB如果表没有用户定义的聚簇索引,则这是一个聚簇索引。第二个索引(i1)是用户定义的二级索引。
这INDEX_ID是在实例中的所有数据库中唯一的索引的标识符。在TABLE_ID识别出索引与相关联的表。索引TYPE值指示索引
的类型(1 =集群索引,0 =辅助索引)。该
N_FILEDS值是构成索引的字段的数量。PAGE_NO是索引B树的根页码,并且
SPACE是索引所在表空间的ID。非零值表示索引不驻留在系统表空间中。
MERGE_THRESHOLD定义索引页面中数据量的百分比阈值。如果索引页中的数据量在删除某行或通过更新操作缩短行时降至此值(缺省值为50%)以下,则
InnoDB尝试合并索引页与相邻索引页。
使用INDEX_ID来自的信息
INNODB_SYS_INDEXES,查询
INNODB_SYS_FIELDS有关索引字段的信息i1。
MySQL的> SELECT * FROM INFORMATION_SCHEMA.INNODB_SYS_FIELDS where INDEX_ID = 112 \G
*************************** 1. row ******************** *******
INDEX_ID:112
名称:col1
POS:0
INNODB_SYS_FIELDS提供
NAME索引内的索引字段及其序号位置。如果索引(i1)已在多个字段中定义,
INNODB_SYS_FIELDS则会为每个索引字段提供元数据。
利用SPACE从信息
INNODB_SYS_TABLES,查询
INNODB_SYS_TABLESPACES表中有关表的表空间信息。
MySQL的> SELECT * FROM INFORMATION_SCHEMA.INNODB_SYS_TABLESPACES WHERE SPACE = 57 \G
*************************** 1. row ******************** *******
空间:57
NAME:test / t1
FLAG:0
FILE_FORMAT:羚羊
ROW_FORMAT:紧凑或冗余
PAGE_SIZE:16384
ZIP_PAGE_SIZE:0
除了SPACE表空间的ID和NAME关联的表之外,INNODB_SYS_TABLESPACES
还提供表空间FLAG数据,这是关于表空间格式和存储特性的位级别信息。还提供的表空间
FILE_FORMAT,
ROW_FORMAT,PAGE_SIZE,和其他几个表空间元数据项。
再次
使用该SPACE信息
INNODB_SYS_TABLES,查询INNODB_SYS_DATAFILES表空间数据文件的位置。
MySQL的> SELECT * FROM INFORMATION_SCHEMA.INNODB_SYS_DATAFILES WHERE SPACE = 57 \G
*************************** 1. row ******************** *******
空间:57
路径:./test/t1.ibd
数据文件位于test
MySQL目录下的data目录中。如果
使用
语句的子句在MySQL数据目录之外的位置创建了
文件每表的表空间,则表空间将是完全限定的目录路径。
DATA DIRECTORYCREATE TABLEPATH
作为最后一步,在table t1(TABLE_ID = 71)中插入一行
并查看INNODB_SYS_TABLESTATS表中的数据
。MySQL表优化器使用此表中的数据计算在查询InnoDB表时要使用哪个索引
。这些信息来源于内存中的数据结构。没有相应的内部InnoDB系统表。
MySQL的>INSERT INTO t1 VALUES(5, 'abc', 'def');查询OK,1行受影响(0.06秒) MySQL的>SELECT * FROM INFORMATION_SCHEMA.INNODB_SYS_TABLESTATS where TABLE_ID = 71 \G*************************** 1. row ******************** ******* TABLE_ID:71 NAME:test / t1 STATS_INITIALIZED:已初始化 NUM_ROWS:1 CLUST_INDEX_SIZE:1 OTHER_INDEX_SIZE:0 MODIFIED_COUNTER:1 AUTOINC:0 REF_COUNT:1
该STATS_INITIALIZED字段指示是否收集了该表的统计信息。
NUM_ROWS是表中当前的估计行数。在
CLUST_INDEX_SIZE与
OTHER_INDEX_SIZE场报告后,分别存储集群和二级指标对表在磁盘上的页面数。该
MODIFIED_COUNTER值显示DML操作修改的行数和外键的级联操作。该AUTOINC值是任何基于自动增量操作的下一个数字。在表中没有定义自动增量列t1,所以值为0
REF_COUNT价值是一个计数器。当计数器达到0时,表示表元数据可以从表缓存中逐出。
例14.3外键INFORMATION_SCHEMA系统表
在INNODB_SYS_FOREIGN和
INNODB_SYS_FOREIGN_COLS表格提供了有关外键关系数据。本示例使用具有外键关系的父表和子表来演示在INNODB_SYS_FOREIGN和
INNODB_SYS_FOREIGN_COLS表中找到的
数据。
用父表和子表创建测试数据库:
MySQL的>CREATE DATABASE test;MySQL的>USE test;MySQL的>CREATE TABLE parent (id INT NOT NULL,PRIMARY KEY (id)) ENGINE=INNODB;MySQL的>CREATE TABLE child (id INT, parent_id INT,INDEX par_ind (parent_id),CONSTRAINT fk1FOREIGN KEY (parent_id) REFERENCES parent(id)ON DELETE CASCADE) ENGINE=INNODB;
创建父和子表后,查询
INNODB_SYS_FOREIGN并定位为外键数据test/child
和test/parent外键关系:
MySQL的> SELECT * FROM INFORMATION_SCHEMA.INNODB_SYS_FOREIGN \G
*************************** 1. row ******************** *******
ID:test / fk1
FOR_NAME:测试/孩子
REF_NAME:测试/父母
N_COLS:1
类型:1
元数据包括外键ID
(fk1),该外键是为CONSTRAINT在子表上定义的名称命名的
。这FOR_NAME是定义外键的子表的名称。
REF_NAME是父表的名称(“ 引用 ”表)。
N_COLS是外键索引中的列数。TYPE是一个表示位标志的数值,它提供有关外键列的附加信息。在这种情况下,
TYPE值为1,这表明
ON DELETE CASCADE选项是为外键指定的。INNODB_SYS_FOREIGN有关TYPE值的更多信息,请参阅
表定义
。
使用外键ID查询
INNODB_SYS_FOREIGN_COLS来查看有关外键列的数据。
MySQL的> SELECT * FROM INFORMATION_SCHEMA.INNODB_SYS_FOREIGN_COLS WHERE ID = 'test/fk1' \G
*************************** 1. row ******************** *******
ID:test / fk1
FOR_COL_NAME:parent_id
REF_COL_NAME:ID
POS:0
FOR_COL_NAME是子表中外键列
REF_COL_NAME的名称,是父表中引用列的名称。该
POS值是外键索引内的键字段的序号位置,从零开始。
例14.4加入InnoDB INFORMATION_SCHEMA系统表
此示例演示如何连接三个
InnoDB INFORMATION_SCHEMA
系统表(INNODB_SYS_TABLES,
INNODB_SYS_TABLESPACES和
INNODB_SYS_TABLESTATS)以收集有关雇员示例数据库中表的文件格式,行格式,页面大小和索引大小信息。
以下表名别名用于缩短查询字符串:
一个IF()控制流功能用于解释压缩的表。如果表格被压缩,则索引大小是使用计算
ZIP_PAGE_SIZE而不是
PAGE_SIZE。
CLUST_INDEX_SIZE和
OTHER_INDEX_SIZE以字节为单位进行报告,并将其除以1024*1024提供以兆字节(MB)为单位的索引大小。MB值使用该ROUND()
函数四舍五入为零小数空格。
MySQL的>SELECT a.NAME, a.FILE_FORMAT, a.ROW_FORMAT,@page_size :=IF(a.ROW_FORMAT='Compressed',b.ZIP_PAGE_SIZE, b.PAGE_SIZE)AS page_size,ROUND((@page_size * c.CLUST_INDEX_SIZE)/(1024*1024)) AS pk_mb,ROUND((@page_size * c.OTHER_INDEX_SIZE)/(1024*1024)) AS secidx_mbFROM INFORMATION_SCHEMA.INNODB_SYS_TABLES aINNER JOIN INFORMATION_SCHEMA.INNODB_SYS_TABLESPACES b on a.NAME = b.NAMEINNER JOIN INFORMATION_SCHEMA.INNODB_SYS_TABLESTATS c on b.NAME = c.NAMEWHERE a.NAME LIKE 'employees/%'ORDER BY a.NAME DESC;+ ------------------------ + ------------- + ---------- - + ----------- + ------- + ----------- + | NAME | FILE_FORMAT | ROW_FORMAT | page_size | pk_mb | secidx_mb | + ------------------------ + ------------- + ---------- - + ----------- + ------- + ----------- + | 员工/职位| 羚羊| 紧凑| 16384 | 20 | 11 | | 员工/薪水| 羚羊| 紧凑| 16384 | 91 | 33 | | 员工/员工| 羚羊| 紧凑| 16384 | 15 | 0 | | employees / dept_manager | 羚羊| 紧凑| 16384 | 0 | 0 | | employees / dept_emp | 羚羊| 紧凑| 16384 | 12 | 10 | | 员工/部门| 羚羊| 紧凑| 16384 | 0 | 0 | + ------------------------ + ------------- + ---------- - + ----------- + ------- + ----------- +
随着在MySQL 5.6.4中引入FULLTEXT对InnoDB表的索引支持,下列表格被添加到INFORMATION_SCHEMA
数据库中:
MySQL的> SHOW TABLES FROM INFORMATION_SCHEMA LIKE 'INNODB_FT%';
+ ------------------------------------------- +
| Tables_in_INFORMATION_SCHEMA(INNODB_FT%)|
+ ------------------------------------------- +
| INNODB_FT_CONFIG |
| INNODB_FT_BEING_DELETED |
| INNODB_FT_DELETED |
| INNODB_FT_DEFAULT_STOPWORD |
| INNODB_FT_INDEX_TABLE |
| INNODB_FT_INDEX_CACHE |
+ ------------------------------------------- +
INNODB_FT_CONFIG:显示关于表的FULLTEXT索引和关联处理的元数据InnoDB。
INNODB_FT_BEING_DELETED:提供INNODB_FT_DELETED仅在OPTIMIZE
TABLE维护操作期间使用的表的快照
。当
OPTIMIZE TABLE运行时,该
INNODB_FT_BEING_DELETED表被清空,DOC_IDs从除去
INNODB_FT_DELETED表。由于内容
INNODB_FT_BEING_DELETED通常具有较短的使用寿命,因此此表对于监视或调试具有有限的实用性。有关OPTIMIZE TABLE在带FULLTEXT索引的表上
运行的信息
,请参见
第12.9.6节“微调MySQL全文搜索”。
INNODB_FT_DELETED:记录从表FULLTEXT索引中删除的行InnoDB。为了避免在索引的DML操作期间进行昂贵的索引重组
InnoDB FULLTEXT,有关新删除的单词的信息将单独存储,在执行文本搜索时过滤出搜索结果,并且仅在运行时从主搜索索引中删除OPTIMIZE TABLE。
INNODB_FT_DEFAULT_STOPWORD:保存创建索引时默认使用
的停用词表的列表FULLTEXT。
有关该INNODB_FT_DEFAULT_STOPWORD表的信息
,请参见第12.9.4节“全文停用词”。
INNODB_FT_INDEX_TABLE:包含有关用于处理针对FULLTEXT索引的文本搜索的倒排索引的数据。
INNODB_FT_INDEX_CACHE:包含有关FULLTEXT索引中新插入行的标记信息
。为避免在DML操作过程中进行昂贵的索引重组,单独存储有关新索引的单词的信息,并且仅在OPTIMIZE
TABLE运行时,服务器关闭时或缓存大小超过由innodb_ft_cache_sizeor
定义的限制时
与主搜索索引结合使用innodb_ft_total_cache_size。
除
INNODB_FT_DEFAULT_STOPWORD表格之外,您必须将innodb_ft_aux_table
配置变量设置为
包含索引的表格(database_name/ table_name)的名称FULLTEXT。否则,InnoDB FULLTEXT索引
INFORMATION_SCHEMA表显示为空。
例14.5 InnoDB FULLTEXT索引INFORMATION_SCHEMA表
本示例使用带FULLTEXT
索引的表来演示FULLTEXT索引
INFORMATION_SCHEMA表中包含的
数据。
用a创建一个表 FULLTEXT索引并插入一些数据:
MySQL的>CREATE TABLE articles (id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY,title VARCHAR(200),body TEXT,FULLTEXT (title,body)) ENGINE=InnoDB;MySQL的>INSERT INTO articles (title,body) VALUES('MySQL Tutorial','DBMS stands for DataBase ...'),('How To Use MySQL Well','After you went through a ...'),('Optimizing MySQL','In this tutorial we will show ...'),('1001 MySQL Tricks','1. Never run mysqld as root. 2. ...'),('MySQL vs. YourSQL','In the following database comparison ...'),('MySQL Security','When configured properly, MySQL ...');
将innodb_ft_aux_table
变量设置为具有FULLTEXT索引的表的名称
。如果未设置此变量,则InnoDB
FULLTEXT
INFORMATION_SCHEMA表格显示为空,但
INNODB_FT_DEFAULT_STOPWORD
表格。
SET GLOBAL innodb_ft_aux_table ='test / articles';
查询INNODB_FT_INDEX_CACHE
表格,该表格显示有关FULLTEXT索引中新插入行的信息。为避免在DML操作期间进行昂贵的索引重组,FULLTEXT
直到OPTIMIZE
TABLE运行(或直到服务器关闭或超出缓存限制)时,新插入的行的数据才会保留在索引缓存中。
MySQL的> SELECT * FROM INFORMATION_SCHEMA.INNODB_FT_INDEX_CACHE LIMIT 5;
+ ------------ + -------------- + ------------- + ------- ---- + -------- + ---------- +
| WORD | FIRST_DOC_ID | LAST_DOC_ID | DOC_COUNT | DOC_ID | 位置|
+ ------------ + -------------- + ------------- + ------- ---- + -------- + ---------- +
| 1001 | 5 | 5 | 1 | 5 | 0 |
| 之后| 3 | 3 | 1 | 3 | 22 |
| 比较| 6 | 6 | 1 | 6 | 44 |
| 配置为| 7 | 7 | 1 | 7 | 20 |
| 数据库| 2 | 6 | 2 | 2 | 31 |
+ ------------ + -------------- + ------------- + ------- ---- + -------- + ---------- +
启用
innodb_optimize_fulltext_only
并OPTIMIZE TABLE在包含FULLTEXT索引的表上运行。此操作将FULLTEXT索引缓存的内容刷新
到主
FULLTEXT索引。
innodb_optimize_fulltext_only
改变OPTIMIZE
TABLE语句在InnoDB表格上的操作
方式,并打算在使用InnoDB表格
进行维护操作期间暂时启用
FULLTEXT索引的。
MySQL的>SET GLOBAL innodb_optimize_fulltext_only=ON;查询OK,0行受影响(0.00秒) MySQL的>OPTIMIZE TABLE articles;+ --------------- + ---------- + ---------- + ---------- + | 表| 操作| Msg_type | Msg_text | + --------------- + ---------- + ---------- + ---------- + | test.articles | 优化| 状态| 好的| + --------------- + ---------- + ---------- + ---------- +
查询INNODB_FT_INDEX_TABLE
表以查看主
FULLTEXT索引中的数据信息,包括刚刚从FULLTEXT索引缓存刷新的数据信息
。
MySQL的> SELECT * FROM INFORMATION_SCHEMA.INNODB_FT_INDEX_TABLE LIMIT 5;
+ ------------ + -------------- + ------------- + ------- ---- + -------- + ---------- +
| WORD | FIRST_DOC_ID | LAST_DOC_ID | DOC_COUNT | DOC_ID | 位置|
+ ------------ + -------------- + ------------- + ------- ---- + -------- + ---------- +
| 1001 | 5 | 5 | 1 | 5 | 0 |
| 之后| 3 | 3 | 1 | 3 | 22 |
| 比较| 6 | 6 | 1 | 6 | 44 |
| 配置为| 7 | 7 | 1 | 7 | 20 |
| 数据库| 2 | 6 | 2 | 2 | 31 |
+ ------------ + -------------- + ------------- + ------- ---- + -------- + ---------- +
该INNODB_FT_INDEX_CACHE表格现在是空的,因为OPTIMIZE
TABLE操作刷新了
FULLTEXT索引缓存。
MySQL的> SELECT * FROM INFORMATION_SCHEMA.INNODB_FT_INDEX_CACHE LIMIT 5;
空集(0.00秒)
从test/articles表中删除一些记录
。
MySQL的> DELETE FROM test.articles WHERE id < 4;
查询OK,3行受影响(0.11秒)
查询INNODB_FT_DELETED
表格。该表记录从FULLTEXT索引中删除的行
。为避免在DML操作过程中进行昂贵的索引重组,有关新删除记录的信息将单独存储,当您执行文本搜索时会从搜索结果中过滤掉,并在运行时从主搜索索引中删除
OPTIMIZE TABLE。
MySQL的> SELECT * FROM INFORMATION_SCHEMA.INNODB_FT_DELETED;
+ -------- +
| DOC_ID |
+ -------- +
| 2 |
| 3 |
| 4 |
+ -------- +
运行OPTIMIZE TABLE删除已删除的记录。
MySQL的> OPTIMIZE TABLE articles;
+ --------------- + ---------- + ---------- + ---------- +
| 表| 操作| Msg_type | Msg_text |
+ --------------- + ---------- + ---------- + ---------- +
| test.articles | 优化| 状态| 好的|
+ --------------- + ---------- + ---------- + ---------- +
该INNODB_FT_DELETED表现在应该显示为空。
MySQL的> SELECT * FROM INFORMATION_SCHEMA.INNODB_FT_DELETED;
空集(0.00秒)
查询INNODB_FT_CONFIG
表格。此表包含有关FULLTEXT索引和相关处理的元数据
:
optimize_checkpoint_limit是OPTIMIZE TABLE运行停止后的秒数
。
synced_doc_id是下一个
DOC_ID要发布的。
stopword_table_name是database/table用户定义的停用词表的
名称。如果没有用户定义的停用词表,该栏位显示为空。
use_stopword指示是否使用停用词表,该表是在FULLTEXT索引创建时定义的
。
MySQL的> SELECT * FROM INFORMATION_SCHEMA.INNODB_FT_CONFIG;
+ --------------------------- + ------- +
| KEY | VALUE |
+ --------------------------- + ------- +
| optimize_checkpoint_limit | 180 |
| synced_doc_id | 8 |
| stopword_table_name | |
| use_stopword | 1 |
+ --------------------------- + ------- +
该InnoDB
INFORMATION_SCHEMA缓冲池表提供了有关内页缓冲池的状态信息和元数据InnoDB缓冲池。这些表格在MySQL 5.6.2中引入,后来被移植到MySQL 5.5(在MySQL 5.5.28中)和MySQL 5.1(在MySQL 5.1.66中)。
该InnoDB
INFORMATION_SCHEMA缓冲池表包括那些列举如下:
MySQL的> SHOW TABLES FROM INFORMATION_SCHEMA LIKE 'INNODB_BUFFER%';
+ ----------------------------------------------- +
| Tables_in_INFORMATION_SCHEMA(INNODB_BUFFER%)|
+ ----------------------------------------------- +
| INNODB_BUFFER_PAGE_LRU |
| INNODB_BUFFER_PAGE |
| INNODB_BUFFER_POOL_STATS |
+ ----------------------------------------------- +
INNODB_BUFFER_PAGE:保存有关InnoDB
缓冲池中每个页面的信息。
INNODB_BUFFER_PAGE_LRU:保存有关InnoDB
缓冲池中页面的信息,特别是它们在LRU列表中的排序方式,该列表确定在缓冲池变满时哪些页面要从缓冲池中逐出。该
INNODB_BUFFER_PAGE_LRU表与表具有相同的列
INNODB_BUFFER_PAGE,但该INNODB_BUFFER_PAGE_LRU
表具有LRU_POSITION列而不是BLOCK_ID列。
INNODB_BUFFER_POOL_STATS:提供缓冲池状态信息。许多相同的信息由SHOW ENGINE
INNODB STATUS输出提供
,或者可以使用
InnoDB缓冲池服务器状态变量获得。
查询INNODB_BUFFER_PAGE
表或INNODB_BUFFER_PAGE_LRU
表可能会导致显着的性能开销。不要在生产系统上查询这些表,除非您知道您的查询可能具有的性能影响,并且已经确定它是可接受的。为避免影响性能,请重新创建要在测试实例上调查的问题,并在测试实例上运行查询。
例14.6查询INNODB_BUFFER_PAGE表中的系统数据
该查询通过排除表TABLE_NAME值中
NULL包含斜线/
或句点的页面.(该表格指定用户定义的表格)来提供包含系统数据的近似页数
。
MySQL的>SELECT COUNT(*) FROM INFORMATION_SCHEMA.INNODB_BUFFER_PAGEWHERE TABLE_NAME IS NULL OR (INSTR(TABLE_NAME, '/') = 0 AND INSTR(TABLE_NAME, '.') = 0);+ ---------- + | COUNT(*)| + ---------- + | 1516 | + ---------- +
该查询返回包含系统数据的近似页数,缓冲池页面总数以及包含系统数据的页面的近似百分比。
MySQL的>SELECT(SELECT COUNT(*) FROM INFORMATION_SCHEMA.INNODB_BUFFER_PAGEWHERE TABLE_NAME IS NULL OR (INSTR(TABLE_NAME, '/') = 0 AND INSTR(TABLE_NAME, '.') = 0)) AS system_pages,(SELECT COUNT(*)FROM INFORMATION_SCHEMA.INNODB_BUFFER_PAGE) AS total_pages,(SELECT ROUND((system_pages/total_pages) * 100)) AS system_page_percentage;+ -------------- + ------------- + -------------------- ---- + | system_pages | total_pages | system_page_percentage | + -------------- + ------------- + -------------------- ---- + | 295 | 8192 | 4 | + -------------- + ------------- + -------------------- ---- +
通过查询该PAGE_TYPE值可以确定缓冲池中的系统数据类型。例如,以下查询将返回PAGE_TYPE包含系统数据的页面中的八个不同
值:
MySQL的>SELECT DISTINCT PAGE_TYPE FROM INFORMATION_SCHEMA.INNODB_BUFFER_PAGEWHERE TABLE_NAME IS NULL OR (INSTR(TABLE_NAME, '/') = 0 AND INSTR(TABLE_NAME, '.') = 0);+ ------------------- + | PAGE_TYPE | + ------------------- + | SYSTEM | | IBUF_BITMAP | | UNKNOWN | | FILE_SPACE_HEADER | | INODE | | UNDO_LOG | | ALLOCATED | + ------------------- +
例14.7查询INNODB_BUFFER_PAGE表中的用户数据
此查询提供的通过其中的计数页面包含用户数据的页的近似计数
TABLE_NAME值为NOT
NULL和NOT LIKE
'%INNODB_SYS_TABLES%'。
MySQL的>SELECT COUNT(*) FROM INFORMATION_SCHEMA.INNODB_BUFFER_PAGEWHERE TABLE_NAME IS NOT NULL AND TABLE_NAME NOT LIKE '%INNODB_SYS_TABLES%';+ ---------- + | COUNT(*)| + ---------- + | 7897 | + ---------- +
此查询返回包含用户数据的大概页数,缓冲池页面的总数以及包含用户数据的页面的近似百分比。
MySQL的>SELECT(SELECT COUNT(*) FROM INFORMATION_SCHEMA.INNODB_BUFFER_PAGEWHERE TABLE_NAME IS NOT NULL AND (INSTR(TABLE_NAME, '/') > 0 OR INSTR(TABLE_NAME, '.') > 0)) AS user_pages,(SELECT COUNT(*)FROM INFORMATION_SCHEMA.INNODB_BUFFER_PAGE) AS total_pages,(SELECT ROUND((user_pages/total_pages) * 100)) AS user_page_percentage;+ ------------ + ------------- + ---------------------- + | user_pages | total_pages | user_page_percentage | + ------------ + ------------- + ---------------------- + | 7897 | 8192 | 96 | + ------------ + ------------- + ---------------------- +
此查询使用缓冲池中的页面标识用户定义的表格:
MySQL的>SELECT DISTINCT TABLE_NAME FROM INFORMATION_SCHEMA.INNODB_BUFFER_PAGEWHERE TABLE_NAME IS NOT NULL AND (INSTR(TABLE_NAME, '/') > 0 OR INSTR(TABLE_NAME, '.') > 0)AND TABLE_NAME NOT LIKE '`mysql`.`innodb_%';+ ------------------------- + | TABLE_NAME | + ------------------------- + | `雇员`.`slaries` | | `雇员`.`雇员`| + ------------------------- +
例14.8查询INNODB_BUFFER_PAGE表中的索引数据
有关索引页的信息,请INDEX_NAME使用索引名称查询
列。例如,以下查询返回表中emp_no定义的索引
的页面数和页面总数据大小
employees.salaries:
MySQL的>SELECT INDEX_NAME, COUNT(*) AS Pages,ROUND(SUM(IF(COMPRESSED_SIZE = 0, @@global.innodb_page_size, COMPRESSED_SIZE))/1024/1024)AS 'Total Data (MB)'FROM INFORMATION_SCHEMA.INNODB_BUFFER_PAGEWHERE INDEX_NAME='emp_no' AND TABLE_NAME = '`employees`.`salaries`';+ ------------ + ------- + ----------------- + | INDEX_NAME | 页面| 总数据(MB)| + ------------ + ------- + ----------------- + | emp_no | 1609 | 25 | + ------------ + ------- + ----------------- +
此查询返回employees.salaries表中定义的所有索引的页面数和页面总数据大小
:
MySQL的>SELECT INDEX_NAME, COUNT(*) AS Pages,ROUND(SUM(IF(COMPRESSED_SIZE = 0, @@global.innodb_page_size, COMPRESSED_SIZE))/1024/1024)AS 'Total Data (MB)'FROM INFORMATION_SCHEMA.INNODB_BUFFER_PAGEWHERE TABLE_NAME = '`employees`.`salaries`'GROUP BY INDEX_NAME;+ ------------ + ------- + ----------------- + | INDEX_NAME | 页面| 总数据(MB)| + ------------ + ------- + ----------------- + | emp_no | 1608 | 25 | | PRIMARY | 6086 | 95 | + ------------ + ------- + ----------------- +
例14.9查询INNODB_BUFFER_PAGE_LRU表中的LRU_POSITION数据
该INNODB_BUFFER_PAGE_LRU表保存关于InnoDB缓冲池中的页面的信息
,特别是如何排序它们以确定当缓冲池变满时哪些页面要从缓冲池中逐出。这个页面的定义与for相同INNODB_BUFFER_PAGE,除了这个表格有一LRU_POSITION列而不是一BLOCK_ID列。
此查询计算employees.employees表中页面占用的LRU列表中特定位置的位置数
。
MySQL的>SELECT COUNT(LRU_POSITION) FROM INFORMATION_SCHEMA.INNODB_BUFFER_PAGE_LRUWHERE TABLE_NAME='`employees`.`employees`' AND LRU_POSITION < 3072;+ --------------------- + | COUNT(LRU_POSITION)| + --------------------- + | 548 | + --------------------- +
例14.10查询INNODB_BUFFER_POOL_STATS表
该INNODB_BUFFER_POOL_STATS表提供了类似的信息
SHOW ENGINE INNODB
STATUS和InnoDB缓冲池的状态变量。
MySQL的> SELECT * FROM information_schema.INNODB_BUFFER_POOL_STATS \G
*************************** 1. row ******************** *******
POOL_ID:0
POOL_SIZE:8192
FREE_BUFFERS:1
DATABASE_PAGES:8173
OLD_DATABASE_PAGES:3014
MODIFIED_DATABASE_PAGES:0
PENDING_DECOMPRESS:0
PENDING_READS:0
PENDING_FLUSH_LRU:0
PENDING_FLUSH_LIST:0
PAGES_MADE_YOUNG:15907
PAGES_NOT_MADE_YOUNG:3803101
PAGES_MADE_YOUNG_RATE:0
PAGES_MADE_NOT_YOUNG_RATE:0
NUMBER_PAGES_READ:3270
NUMBER_PAGES_CREATED:13176
NUMBER_PAGES_WRITTEN:15109
PAGES_READ_RATE:0
PAGES_CREATE_RATE:0
PAGES_WRITTEN_RATE:0
NUMBER_PAGES_GET:33069332
HIT_RATE:0
YOUNG_MAKE_PER_THOUSAND_GETS:0
NOT_YOUNG_MAKE_PER_THOUSAND_GETS:0
NUMBER_PAGES_READ_AHEAD:2713
NUMBER_READ_AHEAD_EVICTED:0
READ_AHEAD_RATE:0
READ_AHEAD_EVICTED_RATE:0
LRU_IO_TOTAL:0
LRU_IO_CURRENT:0
UNCOMPRESS_TOTAL:0
UNCOMPRESS_CURRENT:0
作为比较,
SHOW ENGINE INNODB
STATUS输出和InnoDB缓冲池状态变量输出如下所示,基于相同的数据集。
有关SHOW ENGINE INNODB
STATUS输出的更多信息
,请参见
第14.17.3节“InnoDB标准监视器和锁定监视器输出”。
MySQL的> SHOW ENGINE INNODB STATUS \G
...
----------------------
缓冲池和内存
----------------------
总大内存分配137428992
分配的字典内存579084
缓冲池大小8192
免费缓冲区1
数据库页面8173
旧的数据库页面3014
修改数据库页面0
等待读取0
等待写入:LRU 0,刷新列表0,单个页面0
年轻的书15907,而不是年轻的3803101
0.00青少年/秒,0.00非青少年/秒
页面读取3270,创建13176,写入15109
0.00读/秒,0.00创建/秒,0.00写/秒
自上次打印输出以来没有获得缓冲池页面
提前读取的页数为0.00 /秒,不带访问时驱逐为0.00 /秒,随机读取为0.00 /秒
LRU len:8173,unzip_LRU len:0
I / O sum [0]:cur [0],unzip sum [0]:cur [0]
...
有关状态变量说明,请参见 第5.1.7节“服务器状态变量”。
MySQL的> SHOW STATUS LIKE 'Innodb_buffer%';
+ --------------------------------------- + --------- ---- +
| 变量名| 值|
+ --------------------------------------- + --------- ---- +
| Innodb_buffer_pool_dump_status | 没有开始|
| Innodb_buffer_pool_load_status | 没有开始|
| Innodb_buffer_pool_resize_status | 没有开始|
| Innodb_buffer_pool_pages_data | 8173 |
| Innodb_buffer_pool_bytes_data | 133906432 |
| Innodb_buffer_pool_pages_dirty | 0 |
| Innodb_buffer_pool_bytes_dirty | 0 |
| Innodb_buffer_pool_pages_flushed | 15109 |
| Innodb_buffer_pool_pages_free | 1 |
| Innodb_buffer_pool_pages_misc | 18 |
| Innodb_buffer_pool_pages_total | 8192 |
| Innodb_buffer_pool_read_ahead_rnd | 0 |
| Innodb_buffer_pool_read_ahead | 2713 |
| Innodb_buffer_pool_read_ahead_evicted | 0 |
| Innodb_buffer_pool_read_requests | 33069332 |
| Innodb_buffer_pool_reads | 558 |
| Innodb_buffer_pool_wait_free | 0 |
| Innodb_buffer_pool_write_requests | 11985961 |
+ --------------------------------------- + --------- ---- +
该INNODB_METRICS表在MySQL 5.6.2中引入,将所有InnoDB
性能和资源相关的计数器合并到一个
INFORMATION_SCHEMA表中。
INNODB_METRICS
以下示例中显示
了该表的列。有关每列的说明,请参见第24.31.15节“INFORMATION_SCHEMA INNODB_METRICS表”。
MySQL的> SELECT * FROM INFORMATION_SCHEMA.INNODB_METRICS WHERE NAME="dml_inserts" \G
*************************** 1. row ******************** *******
名称:dml_inserts
SUBSYSTEM:dml
COUNT:46273
MAX_COUNT:46273
MIN_COUNT:NULL
AVG_COUNT:492.2659574468085
COUNT_RESET:46273
MAX_COUNT_RESET:46273
MIN_COUNT_RESET:NULL
AVG_COUNT_RESET:NULL
TIME_ENABLED:2014-11-28 16:07:53
TIME_DISABLED:NULL
TIME_ELAPSED:94
TIME_RESET:NULL
状态:启用
TYPE:status_counter
注释:插入的行数
您可以使用以下配置选项启用,禁用和重置计数器:
innodb_monitor_enable:启用一个或多个计数器。
SET GLOBAL innodb_monitor_enable = [counter-name | module_name | pattern | all];
innodb_monitor_disable:禁用一个或多个计数器。
SET GLOBAL innodb_monitor_disable = [counter-name | module_name | pattern | all];
innodb_monitor_reset:将一个或多个计数器的计数值重置为零。
SET GLOBAL innodb_monitor_reset = [counter-name | module_name | pattern | all];
innodb_monitor_reset_all:重置一个或多个计数器的所有值。使用前必须禁用计数器
innodb_monitor_reset_all。
SET GLOBAL innodb_monitor_reset_all = [counter-name | module_name | pattern | all];
您也可以在启动时使用MySQL服务器配置文件启用计数器和计数器模块。例如,要启用
log模块
metadata_table_handles_opened和
metadata_table_handles_closed计数器,请在配置文件的[mysqld]部分中输入以下行my.cnf。
的[mysqld] innodb_monitor_enable = module_recovery,metadata_table_handles_opened,metadata_table_handles_closed
在配置文件中启用多个计数器或模块时,必须指定innodb_monitor_enable
配置选项,然后指定
用逗号分隔的计数器和模块名称,如上例所示。只有innodb_monitor_enable您的配置文件中可以使用该
选项。禁用和重置配置选项仅在命令行上受支持。
由于每个计数器都会在服务器上产生一定程度的运行时间开销,因此通常在实验和基准测试期间在测试和开发服务器上启用更多计数器,并且只启用生产服务器上的计数器来诊断已知问题或监视可能成为瓶颈的方面特定服务器和工作量。
INNODB_METRICS表中
的计数器
可能会发生变化,所以对于最新的列表,查询正在运行的MySQL服务器。
默认启用的计数器对应于那些使用的计数器
SHOW ENGINE INNODB
STATUS。所使用的计数器
在系统级别上SHOW ENGINE INNODB
STATUS始终处于“ 打开 ”状态,但可以INNODB_METRICS根据需要禁用这些计数器
。此外,计数器状态不是持久的。除非另行指定,否则计数器将在服务器重新启动时恢复为其默认启用或禁用状态。
如果您运行的程序受到INNODB_METRICS表格添加或更改的影响,建议您INNODB_METRICS在升级之前查看发行说明并在新版本中查询
表格。
MySQL的> SELECT name, subsystem, status FROM INFORMATION_SCHEMA.INNODB_METRICS ORDER BY NAME;
------------------------------------------ + ------ + --------------- + ---------- +
| 名称| 子系统| 状态|
------------------------------------------ + ------ + --------------- + ---------- +
| adaptive_hash_pages_added | adaptive_hash_index | 禁用|
| adaptive_hash_pages_removed | adaptive_hash_index | 禁用|
| adaptive_hash_rows_added | adaptive_hash_index | 禁用|
| adaptive_hash_rows_deleted_no_hash_entry | adaptive_hash_index | 禁用|
| adaptive_hash_rows_removed | adaptive_hash_index | 禁用|
| adaptive_hash_rows_updated | adaptive_hash_index | 禁用|
| adaptive_hash_searches | adaptive_hash_index | 启用|
| adaptive_hash_searches_btree | adaptive_hash_index | 启用|
| buffer_data_reads | 缓冲区| 启用|
| buffer_data_written | 缓冲区| 启用|
| buffer_flush_adaptive | 缓冲区| 禁用|
| buffer_flush_adaptive_avg_pass | 缓冲区| 禁用|
| buffer_flush_adaptive_avg_time_est | 缓冲区| 禁用|
| buffer_flush_adaptive_avg_time_slot | 缓冲区| 禁用|
| buffer_flush_adaptive_avg_time_thread | 缓冲区| 禁用|
| buffer_flush_adaptive_pages | 缓冲区| 禁用|
| buffer_flush_adaptive_total_pages | 缓冲区| 禁用|
| buffer_flush_avg_page_rate | 缓冲区| 禁用|
| buffer_flush_avg_pass | 缓冲区| 禁用|
| buffer_flush_avg_time | 缓冲区| 禁用|
| buffer_flush_background | 缓冲区| 禁用|
| buffer_flush_background_pages | 缓冲区| 禁用|
| buffer_flush_background_total_pages | 缓冲区| 禁用|
| buffer_flush_batches | 缓冲区| 禁用|
| buffer_flush_batch_num_scan | 缓冲区| 禁用|
| buffer_flush_batch_pages | 缓冲区| 禁用|
| buffer_flush_batch_scanned | 缓冲区| 禁用|
| buffer_flush_batch_scanned_per_call | 缓冲区| 禁用|
| buffer_flush_batch_total_pages | 缓冲区| 禁用|
| buffer_flush_lsn_avg_rate | 缓冲区| 禁用|
| buffer_flush_neighbor | 缓冲区| 禁用|
| buffer_flush_neighbor_pages | 缓冲区| 禁用|
| buffer_flush_neighbor_total_pages | 缓冲区| 禁用|
| buffer_flush_n_to_flush_by_age | 缓冲区| 禁用|
| buffer_flush_n_to_flush_requested | 缓冲区| 禁用|
| buffer_flush_pct_for_dirty | 缓冲区| 禁用|
| buffer_flush_pct_for_lsn | 缓冲区| 禁用|
| buffer_flush_sync | 缓冲区| 禁用|
| buffer_flush_sync_pages | 缓冲区| 禁用|
| buffer_flush_sync_total_pages | 缓冲区| 禁用|
| buffer_flush_sync_waits | 缓冲区| 禁用|
| buffer_LRU_batches_evict | 缓冲区| 禁用|
| buffer_LRU_batches_flush | 缓冲区| 禁用|
| buffer_LRU_batch_evict_pages | 缓冲区| 禁用|
| buffer_LRU_batch_evict_total_pages | 缓冲区| 禁用|
| buffer_LRU_batch_flush_avg_pass | 缓冲区| 禁用|
| buffer_LRU_batch_flush_avg_time_est | 缓冲区| 禁用|
| buffer_LRU_batch_flush_avg_time_slot | 缓冲区| 禁用|
| buffer_LRU_batch_flush_avg_time_thread | 缓冲区| 禁用|
| buffer_LRU_batch_flush_pages | 缓冲区| 禁用|
| buffer_LRU_batch_flush_total_pages | 缓冲区| 禁用|
| buffer_LRU_batch_num_scan | 缓冲区| 禁用|
| buffer_LRU_batch_scanned | 缓冲区| 禁用|
| buffer_LRU_batch_scanned_per_call | 缓冲区| 禁用|
| buffer_LRU_get_free_loops | 缓冲区| 禁用|
| buffer_LRU_get_free_search | 缓冲区| 禁用|
| buffer_LRU_get_free_waits | 缓冲区| 禁用|
| buffer_LRU_search_num_scan | 缓冲区| 禁用|
| buffer_LRU_search_scanned | 缓冲区| 禁用|
| buffer_LRU_search_scanned_per_call | 缓冲区| 禁用|
| buffer_LRU_single_flush_failure_count | 缓冲区| 禁用|
| buffer_LRU_single_flush_num_scan | 缓冲区| 禁用|
| buffer_LRU_single_flush_scanned | 缓冲区| 禁用|
| buffer_LRU_single_flush_scanned_per_call | 缓冲区| 禁用|
| buffer_LRU_unzip_search_num_scan | 缓冲区| 禁用|
| buffer_LRU_unzip_search_scanned | 缓冲区| 禁用|
| buffer_LRU_unzip_search_scanned_per_call | 缓冲区| 禁用|
| buffer_pages_created | 缓冲区| 启用|
| buffer_pages_read | 缓冲区| 启用|
| buffer_pages_written | 缓冲区| 启用|
| buffer_page_read_blob | buffer_page_io | 禁用|
| buffer_page_read_fsp_hdr | buffer_page_io | 禁用|
| buffer_page_read_ibuf_bitmap | buffer_page_io | 禁用|
| buffer_page_read_ibuf_free_list | buffer_page_io | 禁用|
| buffer_page_read_index_ibuf_leaf | buffer_page_io | 禁用|
| buffer_page_read_index_ibuf_non_leaf | buffer_page_io | 禁用|
| buffer_page_read_index_inode | buffer_page_io | 禁用|
| buffer_page_read_index_leaf | buffer_page_io | 禁用|
| buffer_page_read_index_non_leaf | buffer_page_io | 禁用|
| buffer_page_read_other | buffer_page_io | 禁用|
| buffer_page_read_system_page | buffer_page_io | 禁用|
| buffer_page_read_trx_system | buffer_page_io | 禁用|
| buffer_page_read_undo_log | buffer_page_io | 禁用|
| buffer_page_read_xdes | buffer_page_io | 禁用|
| buffer_page_read_zblob | buffer_page_io | 禁用|
| buffer_page_read_zblob2 | buffer_page_io | 禁用|
| buffer_page_written_blob | buffer_page_io | 禁用|
| buffer_page_written_fsp_hdr | buffer_page_io | 禁用|
| buffer_page_written_ibuf_bitmap | buffer_page_io | 禁用|
| buffer_page_written_ibuf_free_list | buffer_page_io | 禁用|
| buffer_page_written_index_ibuf_leaf | buffer_page_io | 禁用|
| buffer_page_written_index_ibuf_non_leaf | buffer_page_io | 禁用|
| buffer_page_written_index_inode | buffer_page_io | 禁用|
| buffer_page_written_index_leaf | buffer_page_io | 禁用|
| buffer_page_written_index_non_leaf | buffer_page_io | 禁用|
| buffer_page_written_other | buffer_page_io | 禁用|
| buffer_page_written_system_page | buffer_page_io | 禁用|
| buffer_page_written_trx_system | buffer_page_io | 禁用|
| buffer_page_written_undo_log | buffer_page_io | 禁用|
| buffer_page_written_xdes | buffer_page_io | 禁用|
| buffer_page_written_zblob | buffer_page_io | 禁用|
| buffer_page_written_zblob2 | buffer_page_io | 禁用|
| buffer_pool_bytes_data | 缓冲区| 启用|
| buffer_pool_bytes_dirty | 缓冲区| 启用|
| buffer_pool_pages_data | 缓冲区| 启用|
| buffer_pool_pages_dirty | 缓冲区| 启用|
| buffer_pool_pages_free | 缓冲区| 启用|
| buffer_pool_pages_misc | 缓冲区| 启用|
| buffer_pool_pages_total | 缓冲区| 启用|
| buffer_pool_reads | 缓冲区| 启用|
| buffer_pool_read_ahead | 缓冲区| 启用|
| buffer_pool_read_ahead_evicted | 缓冲区| 启用|
| buffer_pool_read_requests | 缓冲区| 启用|
| buffer_pool_size | 服务器| 启用|
| buffer_pool_wait_free | 缓冲区| 启用|
| buffer_pool_write_requests | 缓冲区| 启用|
| compression_pad_decrements | 压缩| 禁用|
| compression_pad_increments | 压缩| 禁用|
| compress_pages_compressed | 压缩| 禁用|
| compress_pages_decompressed | 压缩| 禁用|
| ddl_background_drop_indexes | ddl | 禁用|
| ddl_background_drop_tables | ddl | 禁用|
| ddl_log_file_alter_table | ddl | 禁用|
| ddl_online_create_index | ddl | 禁用|
| ddl_pending_alter_table | ddl | 禁用|
| ddl_sort_file_alter_table | ddl | 禁用|
| dml_deletes | dml | 启用|
| dml_inserts | dml | 启用|
| dml_reads | dml | 禁用|
| dml_updates | dml | 启用|
| file_num_open_files | file_system | 启用|
| ibuf_merges | change_buffer | 启用|
| ibuf_merges_delete | change_buffer | 启用|
| ibuf_merges_delete_mark | change_buffer | 启用|
| ibuf_merges_discard_delete | change_buffer | 启用|
| ibuf_merges_discard_delete_mark | change_buffer | 启用|
| ibuf_merges_discard_insert | change_buffer | 启用|
| ibuf_merges_insert | change_buffer | 启用|
| ibuf_size | change_buffer | 启用|
| icp_attempts | icp | 禁用|
| icp_match | icp | 禁用|
| icp_no_match | icp | 禁用|
| icp_out_of_range | icp | 禁用|
| index_page_discards | 索引| 禁用|
| index_page_merge_attempts | 索引| 禁用|
| index_page_merge_successful | 索引| 禁用|
| index_page_reorg_attempts | 索引| 禁用|
| index_page_reorg_successful | 索引| 禁用|
| index_page_splits | 索引| 禁用|
| innodb_activity_count | 服务器| 启用|
| innodb_background_drop_table_usec | 服务器| 禁用|
| innodb_checkpoint_usec | 服务器| 禁用|
| innodb_dblwr_pages_written | 服务器| 启用|
| innodb_dblwr_writes | 服务器| 启用|
| innodb_dict_lru_count | 服务器| 禁用|
| innodb_dict_lru_usec | 服务器| 禁用|
| innodb_ibuf_merge_usec | 服务器| 禁用|
| innodb_log_flush_usec | 服务器| 禁用|
| innodb_master_active_loops | 服务器| 禁用|
| innodb_master_idle_loops | 服务器| 禁用|
| innodb_master_purge_usec | 服务器| 禁用|
| innodb_master_thread_sleeps | 服务器| 禁用|
| innodb_mem_validate_usec | 服务器| 禁用|
| innodb_page_size | 服务器| 启用|
| innodb_rwlock_sx_os_waits | 服务器| 启用|
| innodb_rwlock_sx_spin_rounds | 服务器| 启用|
| innodb_rwlock_sx_spin_waits | 服务器| 启用|
| innodb_rwlock_s_os_waits | 服务器| 启用|
| innodb_rwlock_s_spin_rounds | 服务器| 启用|
| innodb_rwlock_s_spin_waits | 服务器| 启用|
| innodb_rwlock_x_os_waits | 服务器| 启用|
| innodb_rwlock_x_spin_rounds | 服务器| 启用|
| innodb_rwlock_x_spin_waits | 服务器| 启用|
| lock_deadlocks | 锁定| 启用|
| lock_rec_locks | 锁定| 禁用|
| lock_rec_lock_created | 锁定| 禁用|
| lock_rec_lock_removed | 锁定| 禁用|
| lock_rec_lock_requests | 锁定| 禁用|
| lock_rec_lock_waits | 锁定| 禁用|
| lock_row_lock_current_waits | 锁定| 启用|
| lock_row_lock_time | 锁定| 启用|
| lock_row_lock_time_avg | 锁定| 启用|
| lock_row_lock_time_max | 锁定| 启用|
| lock_row_lock_waits | 锁定| 启用|
| lock_table_locks | 锁定| 禁用|
| lock_table_lock_created | 锁定| 禁用|
| lock_table_lock_removed | 锁定| 禁用|
| lock_table_lock_waits | 锁定| 禁用|
| lock_timeouts | 锁定| 启用|
| log_checkpoints | 恢复| 禁用|
| log_lsn_buf_pool_oldest | 恢复| 禁用|
| log_lsn_checkpoint_age | 恢复| 禁用|
| log_lsn_current | 恢复| 禁用|
| log_lsn_last_checkpoint | 恢复| 禁用|
| log_lsn_last_flush | 恢复| 禁用|
| log_max_modified_age_async | 恢复| 禁用|
| log_max_modified_age_sync | 恢复| 禁用|
| log_num_log_io | 恢复| 禁用|
| log_padded | 恢复| 启用|
| log_pending_checkpoint_writes | 恢复| 禁用|
| log_pending_log_flushes | 恢复| 禁用|
| log_waits | 恢复| 启用|
| log_writes | 恢复| 启用|
| log_write_requests | 恢复| 启用|
| metadata_table_handles_closed | 元数据| 禁用|
| metadata_table_handles_opened | 元数据| 禁用|
| metadata_table_reference_count | 元数据| 禁用|
| os_data_fsyncs | os | 启用|
| os_data_reads | os | 启用|
| os_data_writes | os | 启用|
| os_log_bytes_written | os | 启用|
| os_log_fsyncs | os | 启用|
| os_log_pending_fsyncs | os | 启用|
| os_log_pending_writes | os | 启用|
| os_pending_reads | os | 禁用|
| os_pending_writes | os | 禁用|
| purge_del_mark_records | 清除| 禁用|
| purge_dml_delay_usec | 清除| 禁用|
| purge_invoked | 清除| 禁用|
| purge_resume_count | 清除| 禁用|
| purge_stop_count | 清除| 禁用|
| purge_undo_log_pages | 清除| 禁用|
| purge_upd_exist_or_extern_records | 清除| 禁用|
| trx_active_transactions | 交易| 禁用|
| trx_commits_insert_update | 交易| 禁用|
| trx_nl_ro_commits | 交易| 禁用|
| trx_rollbacks | 交易| 禁用|
| trx_rollbacks_savepoint | 交易| 禁用|
| trx_rollback_active | 交易| 禁用|
| trx_ro_commits | 交易| 禁用|
| trx_rseg_current_size | 交易| 禁用|
| trx_rseg_history_len | 交易| 启用|
| trx_rw_commits | 交易| 禁用|
| trx_undo_slots_cached | 交易| 禁用|
| trx_undo_slots_used | 交易| 禁用|
------------------------------------------ + ------ + --------------- + ---------- +
一组235行(0.01秒)
模块名称对应于表格SUBSYSTEM列中的
值,但不相同INNODB_METRICS。单独启用,禁用或重置计数器,您可以使用模块名称快速启用,禁用或重置特定子系统的所有计数器。例如,用于
module_dml启用与dml子系统关联的所有计数器。
MySQL的>SET GLOBAL innodb_monitor_enable = module_dml;MySQL的>SELECT name, subsystem, status FROM INFORMATION_SCHEMA.INNODB_METRICSWHERE subsystem ='dml';+ ------------- ----------- + + --------- + | 名称| 子系统| 状态| + ------------- ----------- + + --------- + | dml_reads | dml | 启用| | dml_inserts | dml | 启用| | dml_deletes | dml | 启用| | dml_updates | dml | 启用| + ------------- ----------- + + --------- +
下面是可以使用的值
module_name与
innodb_monitor_enable和相关的配置选项,以及相应的一起
SUBSYSTEM名称:
module_adaptive_hash(子系统=
adaptive_hash_index)
module_buffer(子系统=
buffer)
module_buffer_page(子系统=
buffer_page_io)
module_compress(子系统=
compression)
module_ddl(子系统=
ddl)
module_dml(子系统=
dml)
module_file(子系统=
file_system)
module_ibuf_system(子系统=
change_buffer)
module_icp(子系统=
icp)
module_index(子系统=
index)
module_innodb(子系统=
innodb)
module_lock(子系统=
lock)
module_log(子系统=
recovery)
module_metadata(子系统=
metadata)
module_os(子系统=
os)
module_purge(子系统=
purge)
module_trx(子系统=
transaction)
例14.11使用INNODB_METRICS表计数器
此示例演示启用,禁用和重置计数器以及查询INNODB_METRICS表中的计数器数据
。
创建一个简单的InnoDB表格:
MySQL的>USE test;数据库改变 MySQL的>CREATE TABLE t1 (c1 INT) ENGINE=INNODB;查询OK,0行受影响(0.02秒)
启用dml_inserts计数器。
MySQL的> SET GLOBAL innodb_monitor_enable = dml_inserts;
查询OK,0行受影响(0.01秒)
表格栏中
dml_inserts可以找到计数器
的说明:
COMMENTINNODB_METRICS
MySQL的> SELECT NAME, COMMENT FROM INFORMATION_SCHEMA.INNODB_METRICS WHERE NAME="dml_inserts";
+ ------------- + ------------------------- +
| NAME | 评论|
+ ------------- + ------------------------- +
| dml_inserts | 插入的行数|
+ ------------- + ------------------------- +
查询INNODB_METRICS表格中的dml_inserts计数器数据。由于没有执行DML操作,因此计数器值为零或NULL。该TIME_ENABLED和
TIME_ELAPSED值表明,当计数器最后一次启用,因为这个时候多少秒的流逝。
MySQL的> SELECT * FROM INFORMATION_SCHEMA.INNODB_METRICS WHERE NAME="dml_inserts" \G
*************************** 1. row ******************** *******
名称:dml_inserts
SUBSYSTEM:dml
COUNT:0
MAX_COUNT:0
MIN_COUNT:NULL
AVG_COUNT:0
COUNT_RESET:0
MAX_COUNT_RESET:0
MIN_COUNT_RESET:NULL
AVG_COUNT_RESET:NULL
TIME_ENABLED:2014-12-04 14:18:28
TIME_DISABLED:NULL
TIME_ELAPSED:28
TIME_RESET:NULL
状态:启用
TYPE:status_counter
注释:插入的行数
将三行数据插入表中。
MySQL的>INSERT INTO t1 values(1);查询OK,1行受影响(0.00秒) MySQL的>INSERT INTO t1 values(2);查询OK,1行受影响(0.00秒) MySQL的>INSERT INTO t1 values(3);查询OK,1行受影响(0.00秒)
INNODB_METRICS再次
查询表格中的dml_inserts计数器数据。许多计数器值现在已经增加,包括
COUNT,MAX_COUNT,
AVG_COUNT,和
COUNT_RESET。INNODB_METRICS有关这些值的说明,请参阅
表格定义。
MySQL的> SELECT * FROM INFORMATION_SCHEMA.INNODB_METRICS WHERE NAME="dml_inserts"\G
*************************** 1. row ******************** *******
名称:dml_inserts
SUBSYSTEM:dml
COUNT:3
MAX_COUNT:3
MIN_COUNT:NULL
AVG_COUNT:0.046153846153846156
COUNT_RESET:3
MAX_COUNT_RESET:3
MIN_COUNT_RESET:NULL
AVG_COUNT_RESET:NULL
TIME_ENABLED:2014-12-04 14:18:28
TIME_DISABLED:NULL
TIME_ELAPSED:65
TIME_RESET:NULL
状态:启用
TYPE:status_counter
注释:插入的行数
重置dml_inserts计数器,然后INNODB_METRICS再次查询表格中的dml_inserts计数器数据。%_RESET先前报告的
值(例如COUNT_RESET和
MAX_RESET)被设置回零。从启用计数器时累计收集数据的值,如COUNT,
MAX_COUNT和
AVG_COUNT,不受重置的影响。
MySQL的>SET GLOBAL innodb_monitor_reset = dml_inserts;查询OK,0行受影响(0.00秒) MySQL的>SELECT * FROM INFORMATION_SCHEMA.INNODB_METRICS WHERE NAME="dml_inserts"\G*************************** 1. row ******************** ******* 名称:dml_inserts SUBSYSTEM:dml COUNT:3 MAX_COUNT:3 MIN_COUNT:NULL AVG_COUNT:0.03529411764705882 COUNT_RESET:0 MAX_COUNT_RESET:0 MIN_COUNT_RESET:NULL AVG_COUNT_RESET:0 TIME_ENABLED:2014-12-04 14:18:28 TIME_DISABLED:NULL TIME_ELAPSED:85 TIME_RESET:2014-12-04 14:19:44 状态:启用 TYPE:status_counter 注释:插入的行数
要重置所有计数器值,您必须先禁用计数器。禁用计数器将STATUS值设置
为
disbaled。
MySQL的>SET GLOBAL innodb_monitor_disable = dml_inserts;查询OK,0行受影响(0.00秒) MySQL的>SELECT * FROM INFORMATION_SCHEMA.INNODB_METRICS WHERE NAME="dml_inserts"\G*************************** 1. row ******************** ******* 名称:dml_inserts SUBSYSTEM:dml COUNT:3 MAX_COUNT:3 MIN_COUNT:NULL AVG_COUNT:0.030612244897959183 COUNT_RESET:0 MAX_COUNT_RESET:0 MIN_COUNT_RESET:NULL AVG_COUNT_RESET:0 TIME_ENABLED:2014-12-04 14:18:28 TIME_DISABLED:2014-12-04 14:20:06 TIME_ELAPSED:98 TIME_RESET:NULL 状态:已禁用 TYPE:status_counter 注释:插入的行数
计数器和模块名称支持通配符匹配。例如,dml_inserts您可以指定,而不是指定完整的
计数器名称dml_i%。您还可以使用通配符匹配一次启用,禁用或重置多个计数器或模块。例如,指定
dml_%启用,禁用或重置所有以开头的计数器dml_%。
计数器被禁用后,您可以使用该innodb_monitor_reset_all
选项重置所有计数器值
。所有值都设置为零或NULL。
MySQL的>SET GLOBAL innodb_monitor_reset_all = dml_inserts;查询OK,0行受影响(0.00秒) MySQL的>SELECT * FROM INFORMATION_SCHEMA.INNODB_METRICS WHERE NAME="dml_inserts"\G*************************** 1. row ******************** ******* 名称:dml_inserts SUBSYSTEM:dml COUNT:0 MAX_COUNT:NULL MIN_COUNT:NULL AVG_COUNT:NULL COUNT_RESET:0 MAX_COUNT_RESET:NULL MIN_COUNT_RESET:NULL AVG_COUNT_RESET:NULL TIME_ENABLED:NULL TIME_DISABLED:NULL TIME_ELAPSED:NULL TIME_RESET:NULL 状态:已禁用 TYPE:status_counter 注释:插入的行数
INNODB_TEMP_TABLE_INFO提供有关InnoDB在InnoDB实例中当前活动的用户创建的临时表的
信息。它不提供有关InnoDB优化程序使用的内部临时表的信息。
MySQL的> SHOW TABLES FROM INFORMATION_SCHEMA LIKE 'INNODB_TEMP%';
+ --------------------------------------------- +
| Tables_in_INFORMATION_SCHEMA(INNODB_TEMP%)|
+ --------------------------------------------- +
| INNODB_TEMP_TABLE_INFO |
+ --------------------------------------------- +
有关表定义,请参见 第24.31.26节“INFORMATION_SCHEMA INNODB_TEMP_TABLE_INFO表”。
例14.12 INNODB_TEMP_TABLE_INFO
这个例子演示了INNODB_TEMP_TABLE_INFO表格的特征
。
创建一个简单的InnoDB临时表:
MySQL的> CREATE TEMPORARY TABLE t1 (c1 INT PRIMARY KEY) ENGINE=INNODB;
查询INNODB_TEMP_TABLE_INFO查看临时表元数据。
MySQL的> SELECT * FROM INFORMATION_SCHEMA.INNODB_TEMP_TABLE_INFO\G
*************************** 1. row ******************** *******
TABLE_ID:194
名称:#sql7a79_1_0
N_COLS:4
空间:182
PER_TABLE_TABLESPACE:FALSE
IS_COMPRESSED:FALSE
这TABLE_ID 是临时表的唯一标识符。该NAME列显示临时表的系统生成名称,该名称前缀为“ #sql ”。列(数N_COLS)为4,而不是1,因为InnoDB总是创建三个隐藏的表列(DB_ROW_ID,
DB_TRX_ID,和
DB_ROLL_PTR)。
PER_TABLE_TABLESPACE并
IS_COMPRESSED报告
TRUE压缩的临时表。否则,这些字段会报告FALSE。
创建一个压缩的临时表。
MySQL的> CREATE TEMPORARY TABLE t2 (c1 INT) ROW_FORMAT=COMPRESSED ENGINE=INNODB;
INNODB_TEMP_TABLE_INFO
再次
查询。
MySQL的> SELECT * FROM INFORMATION_SCHEMA.INNODB_TEMP_TABLE_INFO\G
*************************** 1. row ******************** *******
TABLE_ID:195
名称:#sql7a79_1_1
N_COLS:4
空间:183
PER_TABLE_TABLESPACE:TRUE
IS_COMPRESSED:TRUE
*************************** 2. row ******************** *******
TABLE_ID:194
名称:#sql7a79_1_0
N_COLS:4
空间:182
PER_TABLE_TABLESPACE:FALSE
IS_COMPRESSED:FALSE
PER_TABLE_TABLESPACE并
IS_COMPRESSED报告
TRUE压缩的临时表。SPACE压缩临时表的ID不同,因为压缩临时表是在单独的每个表的表空间中创建的。在共享临时表空间(ibtmp1)中创建非压缩临时表并报告相同的SPACEID。
重新启动MySQL并进行查询
INNODB_TEMP_TABLE_INFO。
MySQL的> SELECT * FROM INFORMATION_SCHEMA.INNODB_TEMP_TABLE_INFO\G
空集(0.00秒)
返回一个空集,因为
INNODB_TEMP_TABLE_INFO在服务器关闭时,其中的数据不会持久化到磁盘。
创建一个新的临时表。
MySQL的> CREATE TEMPORARY TABLE t1 (c1 INT PRIMARY KEY) ENGINE=INNODB;
查询INNODB_TEMP_TABLE_INFO查看临时表元数据。
MySQL的> SELECT * FROM INFORMATION_SCHEMA.INNODB_TEMP_TABLE_INFO\G
*************************** 1. row ******************** *******
TABLE_ID:196
NAME:#sql7b0e_1_0
N_COLS:4
空间:184
PER_TABLE_TABLESPACE:FALSE
IS_COMPRESSED:FALSE
该SPACEID是新的,因为它是在服务器重新启动时动态生成的。
该INFORMATION_SCHEMA.FILES表提供有关所有InnoDB表空间类型的元数据,其中包括每个表的文件表空间,
常规表空间,
系统表空间,
临时表空间表和撤消表空间(如果存在)。
本节提供了InnoDB特定的使用示例。有关该INFORMATION_SCHEMA.FILES表提供的数据的更多信息
,请参见
第24.8节“INFORMATION_SCHEMA文件表”。
所述INNODB_SYS_TABLESPACES和
INNODB_SYS_DATAFILES表还提供有关的元数据InnoDB的表空间,但数据是仅限于文件每次表和一般的表空间。
此查询InnoDB
从INFORMATION_SCHEMA.FILES表中与InnoDB表空间相关的字段中检索有关系统表空间的
元数据。
INFORMATION_SCHEMA.FILES与InnoDB总是返回NULL 不相关的字段,并从查询中排除。
MySQL的>SELECT FILE_ID, FILE_NAME, FILE_TYPE, TABLESPACE_NAME, FREE_EXTENTS,TOTAL_EXTENTS, EXTENT_SIZE, INITIAL_SIZE, MAXIMUM_SIZE, AUTOEXTEND_SIZE, DATA_FREE, STATUS ENGINEFROM INFORMATION_SCHEMA.FILES WHERE TABLESPACE_NAME LIKE 'innodb_system' \G*************************** 1. row ******************** ******* FILE_ID:0 FILE_NAME:./ibdata1 FILE_TYPE:TABLESPACE TABLESPACE_NAME:innodb_system FREE_EXTENTS:0 TOTAL_EXTENTS:12 EXTENT_SIZE:1048576 INITIAL_SIZE:12582912 MAXIMUM_SIZE:NULL AUTOEXTEND_SIZE:67108864 DATA_FREE:4194304 ENGINE:NORMAL
该查询检索文件每表和文件(一般表FILE_ID空间)的(等同于空间ID)和FILE_NAME(其中包括路径信息)InnoDB。每个表文件和一般表空间都有一个
.ibd文件扩展名。
MySQL的>SELECT FILE_ID, FILE_NAME FROM INFORMATION_SCHEMA.FILESWHERE FILE_NAME LIKE '%.ibd%' ORDER BY FILE_ID;+ --------- + --------------------------------------- + | FILE_ID | FILE_NAME | + --------- + --------------------------------------- + | 2 | ./mysql/plugin.ibd | | 3 | ./mysql/servers.ibd | | 4 | ./mysql/help_topic.ibd | | 5 | ./mysql/help_category.ibd | | 6 | ./mysql/help_relation.ibd | | 7 | ./mysql/help_keyword.ibd | | 8 | ./mysql/time_zone_name.ibd | | 9 | ./mysql/time_zone.ibd | | 10 | ./mysql/time_zone_transition.ibd | | 11 | ./mysql/time_zone_transition_type.ibd | | 12 | ./mysql/time_zone_leap_second.ibd | | 13 | ./mysql/innodb_table_stats.ibd | | 14 | ./mysql/innodb_index_stats.ibd | | 15 | ./mysql/slave_relay_log_info.ibd | | 16 | ./mysql/slave_master_info.ibd | | 17 | ./mysql/slave_worker_info.ibd | | 18 | ./mysql/gtid_executed.ibd | | 19 | ./mysql/server_cost.ibd | | 20 | ./mysql/engine_cost.ibd | | 21 | ./sys/sys_config.ibd | | 23 | ./test/t1.ibd | | 26 | /home/user/test/test/t2.ibd | + --------- + --------------------------------------- +
该查询检索FILE_ID和
FILE_NAME用于InnoDB
临时表空间。临时表空间文件名以前缀为ibtmp。
MySQL的>SELECT FILE_ID, FILE_NAME FROM INFORMATION_SCHEMA.FILESWHERE FILE_NAME LIKE '%ibtmp%';+ --------- + ----------- + | FILE_ID | FILE_NAME | + --------- + ----------- + | 22 | ./ibtmp1 | + --------- + ----------- +
同样,InnoDB撤消表空间文件名称的前缀为undo。下面的查询返回的FILE_ID和
FILE_NAME为InnoDB撤消表空间,如果单独的还原表进行配置。
MySQL的>SELECT FILE_ID, FILE_NAME FROM INFORMATION_SCHEMA.FILESWHERE FILE_NAME LIKE '%undo%';
本节简要介绍
InnoDB与Performance Schema的集成。有关全面的性能模式文档,请参见
第25章MySQL性能模式。
您可以InnoDB
使用MySQL 性能模式功能分析某些内部操作
。此类调整主要针对评估优化策略以克服性能瓶颈的专家用户。DBA还可以将此功能用于容量规划,以查看其典型工作负载是否遇到CPU,RAM和磁盘存储的特定组合的任何性能瓶颈; 如果是的话,可以通过增加系统某些部分的容量来判断性能是否可以得到改善。
要使用此功能来检查InnoDB
性能:
您一定熟悉如何使用
性能模式功能。例如,您应该知道如何启用仪器和消费者,以及如何查询
performance_schema表以检索数据。有关介绍性概述,请参见
第25.1节“性能架构快速入门”。
您应该熟悉可用的性能模式工具InnoDB。要查看
InnoDB相关的乐器,可以在setup_instruments表格中查询
包含' innodb'的乐器名称。
MySQL的> SELECT * FROM setup_instruments WHERE NAME LIKE '%innodb%';
+ ------------------------------------------------- ------ + --------- + ------- +
| NAME | ENABLED | TIMED |
+ ------------------------------------------------- ------ + --------- + ------- +
| wait / synch / mutex / innodb / commit_cond_mutex | NO | NO |
| wait / synch / mutex / innodb / innobase_share_mutex | NO | NO |
| wait / synch / mutex / innodb / autoinc_mutex | NO | NO |
| wait / synch / mutex / innodb / buf_pool_mutex | NO | NO |
| wait / synch / mutex / innodb / buf_pool_zip_mutex | NO | NO |
| 等待/同步/互斥/ innodb / cache_last_read_mutex | NO | NO |
| wait / synch / mutex / innodb / dict_foreign_err_mutex | NO | NO |
| 等待/同步/互斥/ innodb / dict_sys_mutex | NO | NO |
| wait / synch / mutex / innodb / recalc_pool_mutex | NO | NO |
| wait / synch / mutex / innodb / file_format_max_mutex | NO | NO |
...
| wait / io / file / innodb / innodb_data_file | 是| 是|
| wait / io / file / innodb / innodb_log_file | 是| 是|
| wait / io / file / innodb / innodb_temp_file | 是| 是|
| stage / innodb / alter table(end)| 是| 是|
| stage / innodb / alter table(flush)| 是| 是|
| stage / innodb / alter table(insert)| 是| 是|
| stage / innodb / alter table(日志应用索引)| 是| 是|
| stage / innodb / alter table(日志应用表)| 是| 是|
| stage / innodb / alter table(合并排序)| 是| 是|
| stage / innodb / alter table(读取PK和内部排序)| 是| 是|
| stage / innodb /缓冲池加载| 是| 是|
| 内存/ innodb / buf_buf_pool | NO | NO |
| 内存/ innodb / dict_stats_bg_recalc_pool_t | NO | NO |
| 内存/ innodb / dict_stats_index_map_t | NO | NO |
| 内存/ innodb / dict_stats_n_diff_on_level | NO | NO |
| 内存/ innodb / other | NO | NO |
| 内存/ innodb / row_log_buf | NO | NO |
| 内存/ innodb / row_merge_sort | NO | NO |
| 内存/ innodb / std | NO | NO |
| 内存/ innodb / sync_debug_latches | NO | NO |
| 内存/ innodb / trx_sys_t :: rw_trx_ids | NO | NO |
...
+ ------------------------------------------------- ------ + --------- + ------- +
一套155行(0.00秒)
有关检测InnoDB对象的其他信息
,可以查询性能模式
实例表,其中提供了有关检测对象的附加信息。与相关的实例表
InnoDB包括:
与此InnoDB
缓冲池相关的互斥锁和RW锁不包括在此范围内; 这同样适用于SHOW ENGINE INNODB
MUTEX命令的输出。
例如,要查看InnoDB执行文件I / O检测时由性能模式看到的有关检测文件对象的信息
,可以发出以下查询:
MySQL的> SELECT * FROM file_instances WHERE EVENT_NAME LIKE '%innodb%'\G
*************************** 1. row ******************** *******
FILE_NAME:/path/to/mysql-5.7/data/ibdata1
EVENT_NAME:wait / io / file / innodb / innodb_data_file
OPEN_COUNT:3
*************************** 2. row ******************** *******
FILE_NAME:/path/to/mysql-5.7/data/ib_logfile0
EVENT_NAME:wait / io / file / innodb / innodb_log_file
OPEN_COUNT:2
*************************** 3. row ******************** *******
FILE_NAME:/path/to/mysql-5.7/data/ib_logfile1
EVENT_NAME:wait / io / file / innodb / innodb_log_file
OPEN_COUNT:2
*************************** 4. row ******************** *******
FILE_NAME:/path/to/mysql-5.7/data/mysql/engine_cost.ibd
EVENT_NAME:wait / io / file / innodb / innodb_data_file
OPEN_COUNT:3
...
您应该熟悉
performance_schema存储InnoDB事件数据的表
。与InnoDB相关事件相关的表格
包括:
在等待事件表,其存储等待事件。
该 汇总 表,提供随时间终止事件的汇总信息。汇总表包含 文件I / O汇总表,汇总有关I / O操作的信息。
Stage Event表,用于存储事件数据
InnoDB ALTER
TABLE和缓冲池加载操作。有关更多信息,请参见
第14.16.1节“使用性能模式监控InnoDB表的ALTER TABLE进度”,以及
使用性能模式监控缓冲池负载进度。
如果您只对InnoDB相关对象感兴趣,请在查询这些表时使用该子句WHERE EVENT_NAME LIKE
'%innodb%'或WHERE NAME LIKE
'%innodb%'(根据需要)。
您可以使用性能模式监控表的
ALTER TABLE
进度。
InnoDB
有七个舞台事件代表不同的阶段
ALTER TABLE。每个阶段事件都会在整个不同阶段进展时报告总体运行情况WORK_COMPLETED和
WORK_ESTIMATED总体
ALTER TABLE运行情况。
WORK_ESTIMATED是用一个公式计算的,该公式考虑了所有ALTER TABLE执行的工作
,并可能在ALTER TABLE
处理过程中进行修改。WORK_COMPLETED和
WORK_ESTIMATED值全部所执行的工作的的抽象表示
ALTER TABLE。
按照发生的顺序,ALTER TABLE
舞台事件包括:
stage/innodb/alter table (read PK and internal
sort):这个阶段ALTER TABLE在阅读主键阶段处于活动
状态。它以开始
WORK_COMPLETED=0并
WORK_ESTIMATED设置为主键中的估计页数。阶段完成后,
WORK_ESTIMATED更新为主键中的实际页数。
stage/innodb/alter table (merge sort):对于ALTER TABLE操作添加的每个索引重复此阶段
。
stage/innodb/alter table (insert):对于ALTER TABLE操作添加的每个索引重复此阶段
。
stage/innodb/alter table (log apply index):该阶段包括ALTER TABLE运行时生成的DML日志的应用程序
。
stage/innodb/alter table (flush):在此阶段开始之前WORK_ESTIMATED,基于冲刷清单的长度更新为更准确的估计值。
stage/innodb/alter table (log apply table):这个阶段包括ALTER TABLE运行时生成的并发DML日志的应用程序。这个阶段的持续时间取决于表格变化的程度。如果没有并发DML在桌面上运行,这个阶段是即时的。
stage/innodb/alter table (end):包括在刷新阶段后出现的任何剩余工作,例如重新应用ALTER TABLE在运行时在表上执行的DML
。
InnoDB ALTER
TABLE 舞台事件目前不占空间索引的增加。
以下示例演示如何启用
stage/innodb/alter table%舞台事件工具和相关的使用者表来监视
ALTER TABLE进度。有关Performance Schema阶段事件工具和相关使用者的信息,请参见
第25.11.5节“性能模式阶段事件表”。
启用stage/innodb/alter%仪器:
MySQL的> UPDATE setup_instruments SET ENABLED = 'YES' WHERE NAME LIKE 'stage/innodb/alter%';
查询OK,7行受影响(0.00秒)
匹配行数:7更改:7警告:0
启用舞台活动消费表,其中包括
events_stages_current,
events_stages_history,和
events_stages_history_long。
MySQL的> UPDATE setup_consumers SET ENABLED = 'YES' WHERE NAME LIKE '%stages%';
查询OK,3行受影响(0.00秒)
匹配行数:3更改:3警告:0
运行一个ALTER TABLE操作。在这个例子中,一个middle_name列被添加到员工样本数据库的employees表中。
MySQL的> ALTER TABLE employees.employees ADD COLUMN middle_name varchar(14) AFTER first_name;
查询OK,0行受影响(9.27秒)
记录:0重复:0警告:0
ALTER
TABLE通过查询性能模式events_stages_current表来
检查操作
的进度。所显示的舞台事件取决于ALTER TABLE当前正在进行的阶段而有所不同
。该WORK_COMPLETED列显示已完成的工作。该
WORK_ESTIMATED列提供了剩余工作的估计。
MySQL的> SELECT EVENT_NAME, WORK_COMPLETED, WORK_ESTIMATED FROM events_stages_current;
+ ------------------------------------------------- ----- + ---------------- + ---------------- +
| EVENT_NAME | WORK_COMPLETED | WORK_ESTIMATED |
+ ------------------------------------------------- ----- + ---------------- + ---------------- +
| stage / innodb / alter table(读取PK和内部排序)| 280 | 1245 |
+ ------------------------------------------------- ----- + ---------------- + ---------------- +
一排(0.01秒)
events_stages_current如果ALTER
TABLE操作已完成
,表格将返回一个空集。在这种情况下,您可以检查events_stages_history
表以查看已完成操作的事件数据。例如:
MySQL的> SELECT EVENT_NAME, WORK_COMPLETED, WORK_ESTIMATED FROM events_stages_history;
+ ------------------------------------------------- ----- + ---------------- + ---------------- +
| EVENT_NAME | WORK_COMPLETED | WORK_ESTIMATED |
+ ------------------------------------------------- ----- + ---------------- + ---------------- +
| stage / innodb / alter table(读取PK和内部排序)| 886 | 1213 |
| stage / innodb / alter table(flush)| 1213 | 1213 |
| stage / innodb / alter table(日志应用表)| 1597 | 1597 |
| stage / innodb / alter table(end)| 1597 | 1597 |
| stage / innodb / alter table(日志应用表)| 1981 | 1981 |
+ ------------------------------------------------- ----- + ---------------- + ---------------- +
5行(0.00秒)
如上所示,该WORK_ESTIMATED值在ALTER TABLE处理过程中进行了修改。初始阶段完成后的估计工作是1213年。ALTER TABLE处理完成后,WORK_ESTIMATED设定为实际值,即1981年。
互斥锁是代码中使用的同步机制,用于强制在给定时间只有一个线程可以访问公共资源。当服务器中执行的两个或更多线程需要访问相同的资源时,这些线程相互竞争。获得对互斥锁的第一个线程会导致其他线程等待,直到释放锁。
对于已InnoDB插装的互斥锁,可以使用性能架构来监视互斥锁等待
。例如,在性能模式表中收集的等待事件数据可以帮助识别等待时间最长或总等待时间最长的互斥量。
以下示例演示如何启用
InnoDB互斥等待工具,如何启用关联的使用者以及如何查询等待事件数据。
要查看可用的InnoDB互斥等待工具,请查询性能模式
setup_instruments表,如下所示。所有的InnoDB互斥等待仪器默认是禁用的。
MySQL的>SELECT * FROM performance_schema.setup_instrumentsWHERE NAME LIKE '%wait/synch/mutex/innodb%';+ ------------------------------------------------- ------ + --------- + ------- + | NAME | ENABLED | TIMED | + ------------------------------------------------- ------ + --------- + ------- + | wait / synch / mutex / innodb / commit_cond_mutex | NO | NO | | wait / synch / mutex / innodb / innobase_share_mutex | NO | NO | | wait / synch / mutex / innodb / autoinc_mutex | NO | NO | | wait / synch / mutex / innodb / buf_pool_mutex | NO | NO | | wait / synch / mutex / innodb / buf_pool_zip_mutex | NO | NO | | 等待/同步/互斥/ innodb / cache_last_read_mutex | NO | NO | | wait / synch / mutex / innodb / dict_foreign_err_mutex | NO | NO | | 等待/同步/互斥/ innodb / dict_sys_mutex | NO | NO | | wait / synch / mutex / innodb / recalc_pool_mutex | NO | NO | | wait / synch / mutex / innodb / file_format_max_mutex | NO | NO | | 等待/同步/互斥/ innodb / fil_system_mutex | NO | NO | | 等待/同步/互斥/ innodb / flush_list_mutex | NO | NO | | 等待/同步/互斥/ innodb / fts_bg_threads_mutex | NO | NO | | 等待/同步/互斥/ innodb / fts_delete_mutex | NO | NO | | 等待/同步/互斥/ innodb / fts_optimize_mutex | NO | NO | | wait / synch / mutex / innodb / fts_doc_id_mutex | NO | NO | | 等待/同步/互斥/ innodb / log_flush_order_mutex | NO | NO | | 等待/同步/互斥/ innodb / hash_table_mutex | NO | NO | | wait / synch / mutex / innodb / ibuf_bitmap_mutex | NO | NO | | wait / synch / mutex / innodb / ibuf_mutex | NO | NO | | wait / synch / mutex / innodb / ibuf_pessimistic_insert_mutex | NO | NO | | 等待/同步/互斥/ innodb / log_sys_mutex | NO | NO | | wait / synch / mutex / innodb / page_zip_stat_per_index_mutex | NO | NO | | 等待/同步/互斥/ innodb / purge_sys_pq_mutex | NO | NO | | 等待/同步/互斥/ innodb / recv_sys_mutex | NO | NO | | wait / synch / mutex / innodb / recv_writer_mutex | NO | NO | | 等待/同步/互斥/ innodb / redo_rseg_mutex | NO | NO | | wait / synch / mutex / innodb / noredo_rseg_mutex | NO | NO | | 等待/同步/互斥/ innodb / rw_lock_list_mutex | NO | NO | | 等待/同步/互斥/ innodb / rw_lock_mutex | NO | NO | | 等待/同步/互斥/ innodb / srv_dict_tmpfile_mutex | NO | NO | | wait / synch / mutex / innodb / srv_innodb_monitor_mutex | NO | NO | | 等待/同步/互斥/ innodb / srv_misc_tmpfile_mutex | NO | NO | | 等待/同步/互斥/ innodb / srv_monitor_file_mutex | NO | NO | | wait / synch / mutex / innodb / buf_dblwr_mutex | NO | NO | | 等待/同步/互斥/ innodb / trx_undo_mutex | NO | NO | | wait / synch / mutex / innodb / trx_pool_mutex | NO | NO | | 等待/同步/互斥/ innodb / trx_pool_manager_mutex | NO | NO | | 等待/同步/互斥/ innodb / srv_sys_mutex | NO | NO | | 等待/同步/互斥/ innodb / lock_mutex | NO | NO | | 等待/同步/互斥/ innodb / lock_wait_mutex | NO | NO | | wait / synch / mutex / innodb / trx_mutex | NO | NO | | 等待/同步/互斥/ innodb / srv_threads_mutex | NO | NO | | wait / synch / mutex / innodb / rtr_active_mutex | NO | NO | | 等待/同步/互斥/ innodb / rtr_match_mutex | NO | NO | | 等待/同步/互斥/ innodb / rtr_path_mutex | NO | NO | | 等待/同步/互斥/ innodb / rtr_ssn_mutex | NO | NO | | wait / synch / mutex / innodb / trx_sys_mutex | NO | NO | | wait / synch / mutex / innodb / zip_pad_mutex | NO | NO | + ------------------------------------------------- ------ + --------- + ------- + 一组49行(0.02秒)
一些InnoDB互斥体实例在服务器启动时创建,并且只有在服务器启动时也启用相关仪器时才会进行插装。为确保所有InnoDB互斥实例都被检测和启用,请将以下performance-schema-instrument规则添加
到您的MySQL配置文件中:
性能架构仪器= '等待/同步/互斥/ innodb的/%= ON'
如果您不需要所有InnoDB互斥锁的等待事件数据
,则可以通过向performance-schema-instrumentMySQL配置文件添加其他规则来禁用特定仪器
。例如,要禁用
InnoDB与全文搜索相关的互斥锁等待事件工具,请添加以下规则:
性能架构仪器= '等待/同步/互斥/ innodb的/ FTS(%)= OFF'
具有较长前缀的规则(例如
wait/synch/mutex/innodb/fts%优先于具有较短前缀的规则,例如)
wait/synch/mutex/innodb/%。
将performance-schema-instrument规则添加
到配置文件后,重新启动服务器。InnoDB除与全文搜索相关的所有互斥锁以外,所有
互斥锁都已启用。要验证,请查询
setup_instruments表格。在
ENABLED与TIMED
列应设置YES为您启用的工具。
MySQL的>SELECT * FROM performance_schema.setup_instrumentsWHERE NAME LIKE '%wait/synch/mutex/innodb%';+ ------------------------------------------------- ------ + --------- + ------- + | NAME | ENABLED | TIMED | + ------------------------------------------------- ------ + --------- + ------- + | wait / synch / mutex / innodb / commit_cond_mutex | 是| 是| | wait / synch / mutex / innodb / innobase_share_mutex | 是| 是| | wait / synch / mutex / innodb / autoinc_mutex | 是| 是| ... | wait / synch / mutex / innodb / zip_pad_mutex | 是| 是| + ------------------------------------------------- ------ + --------- + ------- + 设置49行(0.00秒)
通过更新setup_consumers表来启用等待事件使用者
。等待事件使用者默认是禁用的。
MySQL的>UPDATE performance_schema.setup_consumers SET enabled = 'YES'WHERE name like 'events_waits%';查询OK,3行受影响(0.00秒) 匹配行数:3更改:3警告:0
您可以通过查询setup_consumers
表来验证是否启用了等待事件使用者。的events_waits_current,
events_waits_history和
events_waits_history_long
消费者应该启用。
MySQL的> SELECT * FROM performance_schema.setup_consumers;
+ ---------------------------------- + --------- +
| NAME | ENABLED |
+ ---------------------------------- + --------- +
| events_stages_current | NO |
| events_stages_history | NO |
| events_stages_history_long | NO |
| events_statements_current | 是|
| events_statements_history | 是|
| events_statements_history_long | NO |
| events_transactions_current | 是|
| events_transactions_history | 是|
| events_transactions_history_long | NO |
| events_waits_current | 是|
| events_waits_history | 是|
| events_waits_history_long | 是|
| global_instrumentation | 是|
| thread_instrumentation | 是|
| statement_digest | 是|
+ ---------------------------------- + --------- +
15行(0.00秒)
一旦启用仪器和消费者,运行您要监控的工作负荷。在这个例子中, mysqlslap负载仿真客户端用于模拟工作负载。
外壳>./mysqlslap --auto-generate-sql --concurrency=100 --iterations=10--number-of-queries=1000 --number-char-cols=6 --number-int-cols=6;
查询等待事件数据。在这个例子中,等待事件数据从查询
events_waits_summary_global_by_event_name
,其聚合中找到的数据表
events_waits_current,
events_waits_history和
events_waits_history_long表。数据通过事件名称(EVENT_NAME)进行汇总,事件名称是生成事件的工具的名称。汇总数据包括:
COUNT_STAR
汇总的等待事件的数量。
SUM_TIMER_WAIT
汇总的定时等待事件的总等待时间。
MIN_TIMER_WAIT
汇总的定时等待事件的最短等待时间。
AVG_TIMER_WAIT
汇总的定时等待事件的平均等待时间。
MAX_TIMER_WAIT
汇总的定时等待事件的最长等待时间。
以下查询返回仪器名称(EVENT_NAME),等待事件数量(COUNT_STAR)以及该仪器事件()的总等待时间SUM_TIMER_WAIT。因为默认情况下,等待时间以皮秒为单位(十亿分之一秒),所以等待时间除以1000000000以显示以毫秒为单位的等待时间。数据按降序排列,按汇总等待事件(COUNT_STAR)的数量表示。您可以ORDER BY通过总等待时间调整
子句以排序数据。
MySQL的>SELECT EVENT_NAME, COUNT_STAR, SUM_TIMER_WAIT/1000000000 SUM_TIMER_WAIT_MSFROM performance_schema.events_waits_summary_global_by_event_nameWHERE SUM_TIMER_WAIT > 0 AND EVENT_NAME LIKE 'wait/synch/mutex/innodb/%'ORDER BY COUNT_STAR DESC;+ ------------------------------------------------- - + ------------ + ------------------- + | EVENT_NAME | COUNT_STAR | SUM_TIMER_WAIT_MS | + ------------------------------------------------- - + ------------ + ------------------- + | 等待/同步/互斥/ innodb / os_mutex | 78831 | 10.3283 | | 等待/同步/互斥/ innodb / log_sys_mutex | 41488 | 6510.3233 | | wait / synch / mutex / innodb / trx_sys_mutex | 29770 | 1107.9687 | | 等待/同步/互斥/ innodb / lock_mutex | 24212 | 104.0724 | | wait / synch / mutex / innodb / trx_mutex | 22756 | 1.9421 | | 等待/同步/互斥/ innodb / rseg_mutex | 20333 | 3.6220 | | 等待/同步/互斥/ innodb / dict_sys_mutex | 13422 | 2.2284 | | 等待/同步/互斥/ innodb / mutex_list_mutex | 12694 | 344.1164 | | 等待/同步/互斥/ innodb / fil_system_mutex | 9208 | 0.9542 | | 等待/同步/互斥/ innodb / rw_lock_list_mutex | 8304 | 0.1794 | | 等待/同步/互斥/ innodb / trx_undo_mutex | 6190 | 0.6801 | | wait / synch / mutex / innodb / buf_pool_mutex | 2869 | 29.4623 | | wait / synch / mutex / innodb / innobase_share_mutex | 2005 | 0.1349 | | 等待/同步/互斥/ innodb / flush_list_mutex | 1274 | 0.1300 | | wait / synch / mutex / innodb / file_format_max_mutex | 1016 | 0.0469 | | wait / synch / mutex / innodb / purge_sys_bh_mutex | 1004 | 0.0326 | | wait / synch / mutex / innodb / buf_dblwr_mutex | 640 | 0.0437 | | 等待/同步/互斥/ innodb / log_flush_order_mutex | 437 | 0.0510 | | 等待/同步/互斥/ innodb / recv_sys_mutex | 394 | 0.0202 | | 等待/同步/互斥/ innodb / srv_sys_mutex | 169 | 0.5259 | | 等待/同步/互斥/ innodb / lock_wait_mutex | 154 | 0.1172 | | wait / synch / mutex / innodb / ibuf_mutex | 9 | 0.0027 | | wait / synch / mutex / innodb / srv_innodb_monitor_mutex | 2 | 0.0009 | | 等待/同步/互斥/ innodb / ut_list_mutex | 1 | 0.0001 | | wait / synch / mutex / innodb / recv_writer_mutex | 1 | 0.0005 | + ------------------------------------------------- - + ------------ + ------------------- + 25行(0.01秒)
上述结果集包括启动过程中生成的等待事件数据。要排除此数据,可以events_waits_summary_global_by_event_name
在启动之后和运行工作负载之前立即截断
表。但是,截断操作本身可能会产生可忽略的数量等待事件数据。
MySQL的> TRUNCATE performance_schema.events_waits_summary_global_by_event_name;
InnoDB监视器提供有关
InnoDB内部状态的信息。这些信息对性能调整很有用。
有两种类型的InnoDB显示器:
标准InnoDB监视器显示以下类型的信息:
由主后台线程完成的工作
信号量等待
有关最近的外键和死锁错误的数据
Lock等待交易
表和活动事务持有的记录锁
等待I / O操作和相关统计
插入缓冲区和自适应散列索引统计
重做日志数据
缓冲池统计信息
行操作数据
该InnoDB锁监控打印附加锁信息作为标准的一部分
InnoDB监视器输出。
当InnoDB监视器启用周期性输出时,InnoDB将输出写入
mysqld服务器标准错误输出(stderr)。InnoDB将诊断输出发送给内存缓冲区stderr而不是
stdout固定大小的内存以避免潜在的缓冲区溢出。
在Windows上,stderr除非另行配置,否则将指向默认日志文件。如果要将输出定向到控制台窗口而不是错误日志,请使用--console选项在控制台窗口中的命令提示符下启动服务器
。有关更多信息,请参见第5.4.2.1节“Windows上的错误日志记录”。
在Unix和类Unix系统上,stderr除非另行配置,否则通常指向终端。有关更多信息,请参见第5.4.2.2节“在Unix和类Unix系统上的错误日志记录”。
启用后,InnoDB每15秒监控一次打印数据。这些数据在性能调优中非常有用。作为副作用,SHOW ENGINE INNODB
STATUS每15秒将输出
写入MySQL数据目录中的状态文件。该文件的名称是
,服务器进程ID 在哪里。
当服务器正常关闭时删除文件。如果发生异常关闭,则可能存在这些状态文件的实例,必须手动删除。在删除文件之前,请检查它们是否包含有关异常关闭原因的有用信息。一个
文件只有在创建
innodb_status.pidpidInnoDBinnodb_status.pidinnodb-status-file配置选项已启用。它默认是禁用的。
InnoDB监视器只应在您确实想查看监视器信息时启用,因为输出生成会导致性能下降。另外,如果监视器输出指向错误日志,那么如果您以后忘记禁用监视器,日志可能会变得非常大。
为了帮助排除故障,在特定条件下InnoDB
暂时启用标准InnoDB监视器输出。有关更多信息,请参见
第14.21节“InnoDB故障排除”。
InnoDB监视器输出以包含时间戳和监视器名称的标题开头。例如:
===================================== 2014-10-16 18:37:29 0x7fc2a95c1700 INNODB MONITOR OUTPUT =====================================
标准InnoDBMonitor(INNODB MONITOR OUTPUT)的标题也用于锁定监视器,因为后者会产生相同的输出并增加额外的锁定信息。
该innodb_status_output和
innodb_status_output_locks系统变量用于启用标准的
InnoDB监控和InnoDB
锁定监控。
该PROCESS权限是启用或禁用InnoDB监视器所必需的。
InnoDB通过将innodb_status_output系统变量设置为,
启用标准监视器ON。
SET GLOBAL innodb_status_output = ON;
要禁用标准InnoDB监视器,请设置
innodb_status_output为
OFF。
当你关闭服务器时,
innodb_status_output变量被设置为默认OFF值。
作为启用标准InnoDBMonitor以进行周期性输出的替代方法
,您可以InnoDB使用SHOW ENGINE
INNODB STATUSSQL语句按需获取标准Monitor输出,该语句将输出提取到客户端程序。如果您使用的是mysql
交互式客户端,那么如果将常用的分号语句终结符替换为\G:
MySQL的> SHOW ENGINE INNODB STATUS\G
SHOW ENGINE INNODB
STATUSInnoDB
如果InnoDB启用锁定监视器,输出还包括锁定监视器数据。
InnoDB使用InnoDB标准监视器输出打印锁定监视器数据
。无论是
InnoDB标准监视器和
InnoDB锁显示器必须能够具有
InnoDB锁定监控数据定期打印。
要启用InnoDB锁定监视器,请将innodb_status_output_locks系统变量设置
为ON。无论是
InnoDB标准的监控和
InnoDB锁定显示器必须能够有
InnoDB定期打印锁监视器数据:
SET GLOBAL innodb_status_output = ON; SET GLOBAL innodb_status_output_locks = ON;
要禁用InnoDB锁定监视器,请设置
innodb_status_output_locks为
OFF。设置
innodb_status_output为
OFF也禁用
InnoDB标准监视器。
关闭服务器时,
变量innodb_status_output和
innodb_status_output_locks变量将设置为默认OFF值。
要启用InnoDB锁定监视器
SHOW ENGINE INNODB
STATUS输出,只需启用
innodb_status_output_locks。
锁定监视器与标准监视器相同,只是它包含附加的锁定信息。启用任一监视器以进行周期性输出会打开相同的输出流,但如果锁定监视器已启用,则该流将包含额外信息。例如,如果启用标准监视器和锁定监视器,则会打开单个输出流。该流包括额外的锁定信息,直到您禁用锁定监视器。
使用该SHOW ENGINE INNODB
STATUS语句生成时,标准监视器输出限制为1MB
。此限制不适用于写入tserver标准错误输出(stderr)的输出。
示例标准监视器输出:
MySQL的> SHOW ENGINE INNODB STATUS\G
*************************** 1. row ******************** *******
类型:InnoDB
名称:
状态:
=====================================
2014-10-16 18:37:29 0x7fc2a95c1700 INNODB MONITOR OUTPUT
=====================================
从最近20秒计算的每秒平均值
-----------------
背景线程
-----------------
srv_master_thread循环:38 srv_active,0 srv_shutdown,252 srv_idle
srv_master_thread日志刷新并写入:290
----------
SEMAPHORES
----------
OS WAIT ARRAY INFO:预留计数119
OS WAIT ARRAY INFO:信号计数103
互斥量等待0,循环0,OS等待0
RW共享旋转38,第76轮,OS等待38
RW-excl转2,轮9383715,OS等待3
RW-sx旋转0,轮0,OS等待0
每轮等待旋转次数:0.00互斥量,2.00 RW共享,4691857.50 RW-excl,
0.00 RW-sx
------------------------
最新的外键错误
------------------------
2014-10-16 18:35:18 0x7fc2a95c1700交易:
TRANSACTION 1814,ACTIVE 0秒插入
mysql表在使用1,锁定1
4个锁结构,堆大小1136,3个行锁,撤销日志条目3
MySQL线程ID 2,操作系统线程句柄140474041767680,查询ID 74本地主机
根更新
插入到子值中
(NULL,1)
,(NULL,2)
,(NULL,3)
,(NULL,4)
,(NULL,5)
,(NULL,6)
表“mysql`.`child`的外键约束失败:
,
CONSTRAINT`child_ibfk_1` FOREIGN KEY(`parent_id`)REFERENCES`parent`
(`id`)ON DELETE CASCADE ON UPDATE CASCADE
尝试在索引par_ind元组中添加子表:
DATA TUPLE:2个字段;
0:len 4; 十六进制80000003; asc ;;
1:len 4; 十六进制80000003; asc ;;
但在父表`mysql`.`parent`中,在索引PRIMARY中,
我们可以找到最接近的匹配记录:
物理记录:n_fields 3; 紧凑格式; 信息位0
0:len 4; 十六进制80000004; asc ;;
1:len 6; 十六进制00000000070a; asc ;;
2:len 7; 十六进制aa0000011d0134; asc 4 ;;
------------------------
最新检测到的死锁
------------------------
2014-10-16 18:36:30 0x7fc2a95c1700
***(1)交易:
TRANSACTION 1824,ACTIVE 9秒开始索引读取
mysql表在使用1,锁定1
LOCK WAIT 2锁结构,堆大小1136,1行锁(s)
MySQL线程ID 3,操作系统线程句柄140474041501440,查询ID 80本地主机
根更新
删除从哪里我= 1
***(1)等待这个锁定被允许:
RECORD LOCKS空间ID 35页面号3 n位72索引表GEN_CLUST_INDEX
`mysql`.`t` trx id 1824 lock_mode X等待
记录锁定,堆号2物理记录:n_fields 4; 紧凑格式; 信息
位0
0:len 6; 十六进制000000000200; asc ;;
1:len 6; 十六进制00000000071f; asc ;;
2:len 7; 十六进制b80000012b0110; asc + ;;
3:len 4; 六角形80000001; asc ;;
***(2)交易:
TRANSACTION 1825,ACTIVE 29秒开始索引读取
mysql表在使用1,锁定1
4个锁结构,堆大小1136,3个行锁(s)
MySQL线程ID 2,OS线程句柄140474041767680,查询ID 81本地主机
根更新
删除从哪里我= 1
***(2)锁定(S):
RECORD LOCKS空间ID 35页面号3 n位72索引表GEN_CLUST_INDEX
`mysql`.`t` trx id 1825锁定模式S
记录锁定,堆号1物理记录:n_fields 1; 紧凑格式; 信息
位0
0:len 8; 十六进制73757072656d756d; asc supremum ;;
记录锁定,堆号2物理记录:n_fields 4; 紧凑格式; 信息位0
0:len 6; 十六进制000000000200; asc ;;
1:len 6; 十六进制00000000071f; asc ;;
2:len 7; 十六进制b80000012b0110; asc + ;;
3:len 4; 六角形80000001; asc ;;
***(2)等待此锁定:
RECORD LOCKS空间ID 35页面号3 n位72索引表GEN_CLUST_INDEX
`mysql`.`t` trx id 1825 lock_mode X等待
记录锁定,堆号2物理记录:n_fields 4; 紧凑格式; 信息
位0
0:len 6; 十六进制000000000200; asc ;;
1:len 6; 十六进制00000000071f; asc ;;
2:len 7; 十六进制b80000012b0110; asc + ;;
3:len 4; 六角形80000001; asc ;;
***我们回卷交易(1)
------------
交易
------------
Trx id counter 1950
清除trx的n:o <1933 undo n:o <0状态:正在运行但空闲
历史列表长度23
每个会话的交易清单:
--- TRANSACTION 421949033065200,未开始
0锁结构,堆大小1136,0行锁(s)
--- TRANSACTION 421949033064280,未开始
0锁结构,堆大小1136,0行锁(s)
--- TRANSACTION 1949,活动0秒插入
mysql表在使用1,锁定1
8个锁结构,堆大小1136,1850行锁,撤消日志条目17415
MySQL线程ID 4,操作系统线程句柄140474041235200,查询ID 176本地主机
根更新
INSERT INTO`salaries` VALUES(55723,39746,'1997-02-25','1998-02-25'),
(55723,40758, '1998年2月25日', '1999-02-25'),(55723,44559 '1999-02-25', '2000年2月25日'),
(55723,44081, '2000年2月25日', '2001年2月24日'),(55723,44112, '2001年2月24日', '2001-08-16'),
(55724,46461, '1996年12月6日', '1997年12月6日'),(55724,48916, '1997年12月6日', '1998年12月6日'),
(55724,51269, '1998年12月6日', '1999年12月6日'),(55724,51932, '1999年12月6日', '2000年12月5日'),
(55724,52617, '2000年12月5日', '2001-12-05'),(55724,56658 '2001-12-05', '9999-01-01'),
(55725,40000, '1993年1月30日', '1994年1月30日'),(55725,41472, '1994年1月30日', '1995年1月30日'),
(55725,45293, '1995年1月30日', '1996-01-30'),(55725,473
--------
FILE I / O
--------
I / O线程0状态:等待已完成的aio请求(插入缓冲线程)
I / O线程1状态:等待已完成的aio请求(日志线程)
I / O线程2状态:等待已完成的aio请求(读取线程)
I / O线程3状态:等待已完成的aio请求(读取线程)
I / O线程4状态:等待已完成的aio请求(读取线程)
I / O线程5状态:等待已完成的aio请求(读取线程)
I / O线程6状态:等待已完成的aio请求(写入线程)
I / O线程7状态:等待已完成的aio请求(写入线程)
I / O线程8状态:等待已完成的aio请求(写入线程)
I / O线程9状态:等待已完成的aio请求(写入线程)
等待正常的aio读取:0 [0,0,0,0],aio写入:0 [0,0,0,0],
ibuf aio读取:0,日志i / o's:0,同步i / o's:0
等待刷新(fsync)日志:0; 缓冲池:0
224个OS文件读取,5770个OS文件写入,803个OS fsyncs
0.00读取/秒,0平均字节/读取,264.84写入/秒,23.05 fsyncs /秒
-------------------------------------
INSERT BUFFER和ADAPTIVE HASH INDEX
-------------------------------------
Ibuf:大小1,空闲列表len 0,seg大小2,0合并
合并操作:
插入0,删除标记0,删除0
丢弃的操作:
插入0,删除标记0,删除0
哈希表大小4425293,节点堆有444个缓冲区(s)
68015.25散列搜索/ s,106259.24非散列搜索/ s
---
LOG
---
日志序号165913808
日志刷新到164814979
页面刷新到141544038
最后一个检查点在130503656
0等待日志刷新,0等待chkp写入
258日志I / O完成,6.65日志I / O /秒
----------------------
缓冲池和内存
----------------------
总大内存分配2198863872
分配了字典内存776332
缓冲池大小131072
空闲缓冲区124908
数据库页面5720
旧数据库页面2071
修改的数据页面910
等待读取0
等待写入:LRU 0,刷新列表0,单个页面0
年轻的4页,而不是年轻的0
0.10个年轻人/ s,0.00个非年轻人/ s
页面读取197,创建5523,写入5060
0.00读/秒,190.89创/秒,244.94写/秒
缓冲池命中率为1000/1000,年轻化率为0/1000
0/1000
提前读取的页数为0.00 / s,无需访问驱逐0.00 /秒,随机读取
前进0.00 /秒
LRU len:5720,unzip_LRU len:0
I / O sum [0]:cur [0],unzip sum [0]:cur [0]
----------------------
个人缓冲池信息
----------------------
--- BUFFER POOL 0
缓冲池大小65536
空闲缓冲区62412
数据库页面2899
旧的数据库页面1050
修改的数据库页面449
等待读取0
等待写入:LRU 0,刷新列表0,单个页面0
年轻的3页,而不是年轻的0
0.05个青少年/ s,0.00个非青少年/ s
页数为107,创建2792,编写为2586
0.00读/秒,92.65次/秒,122.89次/秒
缓冲池命中率1000/1000,年轻化率0/1000不为0/1000
提前读取的页数为0.00 /秒,无需访问驱逐0.00 /秒,随机预读
0.00 /秒
LRU len:2899,unzip_LRU len:0
I / O sum [0]:cur [0],unzip sum [0]:cur [0]
---缓冲池1
缓冲池大小65536
空闲缓冲区62496
数据库页面2821
旧数据库页面1021
修改的数据库页面461
等待读取0
等待写入:LRU 0,刷新列表0,单个页面0
年轻的页面1,而不是年轻的0
0.05个青少年/ s,0.00个非青少年/ s
页数为90,创建2731,写入2474
0.00读/秒,98.25创/秒,122.04 /秒
缓冲池命中率1000/1000,年轻化率0/1000不为0/1000
提前读取的页数为0.00 /秒,无需访问驱逐0.00 /秒,随机预读
0.00 /秒
LRU len:2821,unzip_LRU len:0
I / O sum [0]:cur [0],unzip sum [0]:cur [0]
--------------
行操作
--------------
在InnoDB中查询0个,在队列中查询0个
0读取InnoDB内部的视图
进程ID = 35909,主线程ID = 140471692396288,状态:正在休眠
插入的行数1526363,更新了0,删除了3,读取了11
52671.72插入/秒,0.00更新/秒,0.00删除/秒,0.00读/秒
----------------------------
INNODB MONITOR OUTPUT结束
============================
有关标准监视器报告的每个度量标准的说明,请参阅 “ Oracle企业管理器中的 度量标准”一章, 了解MySQL数据库用户指南。
Status
本部分显示时间戳,监视器名称以及每秒平均值所基于的秒数。秒数是当前时间与上次InnoDB打印监视器输出之间的时间间隔。
BACKGROUND THREAD
这些srv_master_thread行显示了主后台线程完成的工作。
SEMAPHORES
本部分报告线程等待信号量以及线程需要旋转或等待互斥锁或rw锁信号量的次数的统计信息。大量等待信号量的线程可能是磁盘I / O或内部争用问题的结果InnoDB。争用可能是由于查询的严重并行性或操作系统线程调度中的问题。设置
innodb_thread_concurrency
系统变量小于默认值可能有助于这种情况。该Spin rounds per wait
行显示每个操作系统等待互斥锁的自旋锁回合数。
互斥量度量由...报告
SHOW ENGINE
INNODB MUTEX。
LATEST FOREIGN KEY ERROR
本节提供有关最新的外键约束错误的信息。如果没有发生此类错误,则不存在。内容包括失败的语句以及失败约束和引用表和引用表的信息。
LATEST DETECTED DEADLOCK
本节提供有关最新死锁的信息。如果没有发生死锁,则不存在。内容显示涉及哪些事务,每个正试图执行的语句,他们拥有和需要的锁,以及InnoDB
决定回滚以打破僵局的事务。本节中报告的锁定模式在
第14.5.1节“InnoDB锁定”中进行了说明。
TRANSACTIONS
如果此部分报告锁定等待,您的应用程序可能会发生锁定争用。输出还可以帮助追踪事务死锁的原因。
FILE I/O
本节提供有关InnoDB用于执行各种类型I / O的线程的信息
。其中前几个专用于一般
InnoDB处理。内容还显示待处理I / O操作的信息以及I / O性能的统计信息。
这些线程的数量由innodb_read_io_threads和
innodb_write_io_threads
参数控制
。请参见第14.14节“InnoDB启动选项和系统变量”。
INSERT BUFFER AND ADAPTIVE HASH INDEX
本部分显示
InnoDB插入缓冲区(也称为更改缓冲区)的状态和自适应散列索引。
有关相关信息,请参见 第14.4.2节“更改缓冲区”和 第14.4.3节“自适应散列索引”。
LOG
本部分显示有关InnoDB日志的信息
。内容包括当前日志序列号,日志已刷新到磁盘的距离以及InnoDB最后一次检查点的位置
。(请参见
第14.12.3节“InnoDB检查点”。)该部分还显示有关待处理写入和写入性能统计信息。
BUFFER POOL AND MEMORY
本节介绍读取和写入页面的统计数据。您可以根据这些数字计算您的查询当前正在执行的数据文件I / O操作的数量。
有关缓冲池统计信息的说明,请参见 第14.6.3.9节“使用InnoDB标准监控器监控缓冲池”。有关缓冲池操作的更多信息,请参见第14.6.3.1节“InnoDB缓冲池”。
ROW OPERATIONS
本部分显示主线程正在执行的操作,包括每种类型的行操作的数量和性能比率。
本节介绍与InnoDB
备份和恢复相关的主题。
有关适用于备份技术的信息
InnoDB,请参见第14.18.1节“InnoDB备份”。
有关时间点恢复,从磁盘故障或损坏中InnoDB
恢复以及如何执行故障恢复的信息,请参见第14.18.2节“InnoDB恢复”。
安全数据库管理的关键是定期进行备份。根据您的数据量,MySQL服务器数量和数据库工作负载,您可以单独或组合使用这些备份技术: 使用MySQL Enterprise Backup进行热备份 ; 通过在MySQL服务器关闭时复制文件进行冷备份 ; 使用mysqldump进行逻辑备份以 获取较小的数据量或记录模式对象的结构。热备份和冷备份是 物理备份,用于复制实际的数据文件,可以由mysqld服务器直接使用, 以加快恢复速度。
使用MySQL Enterprise Backup是备份InnoDB数据的推荐方法。
InnoDB 不支持使用第三方备份工具恢复的数据库。
作为MySQL企业备份组件的一部分,mysqlbackup命令可让您备份正在运行的MySQL实例(包括InnoDB表),同时最大限度地减少操作中断,同时生成数据库的一致快照。当mysqlbackup复制
InnoDB表时,InnoDB可以继续读取和写入
表。MySQL企业备份还可以创建压缩备份文件,并备份表和数据库的子集。结合MySQL二进制日志,用户可以执行时间点恢复。MySQL企业备份是MySQL企业订阅的一部分。有关更多详细信息,请参见第29.2节“MySQL企业备份概述”。
如果您可以关闭MySQL服务器,则可以进行物理备份,该备份由用于InnoDB管理其表的所有文件组成
。使用以下步骤:
执行MySQL服务器的缓慢关闭,并确保它停止没有错误。
将所有InnoDB数据文件(ibdata文件和
.ibd文件)复制到安全的地方。
将表格的所有.frm文件
复制InnoDB到安全的地方。
将所有InnoDB日志文件(ib_logfile文件)复制到安全的地方。
将您的my.cnf配置文件或文件复制到安全的地方。
除物理备份外,建议您定期使用mysqldump转储表来创建逻辑备份
。二进制文件可能会被破坏,而你没有注意到它。转储表存储在人类可读的文本文件中,因此发现表损坏变得更加容易。而且,由于格式更简单,严重数据损坏的可能性更小。mysqldump
还有一个--single-transaction
选项,可以在不锁定其他客户端的情况下制作一致的快照。请参见第7.3.1节“建立备份策略”。
复制适用于InnoDB表格,因此您可以使用MySQL复制功能在要求高可用性的数据库站点上保留数据库副本。见
第14.19节“InnoDB和MySQL复制”。
本节介绍InnoDB恢复。主题包括:
要从InnoDB进行物理备份的时刻将数据库恢复到现在,即使在进行备份之前,也必须启用启用了二进制日志记录的MySQL服务器。要在还原备份后实现时间点恢复,可以应用在进行备份后发生的二进制日志中的更改。请参见
第7.5节“使用二进制日志进行时间点恢复(增量)”。
如果数据库损坏或发生磁盘故障,则必须使用备份执行恢复。在腐败的情况下,首先找到没有损坏的备份。恢复基本备份后,使用mysqlbinlog和 mysql对二进制日志文件进行时间点恢复,以恢复备份后发生的更改。
在某些数据库损坏的情况下,转储,删除和重新创建一个或几个损坏的表就足够了。您可以使用该
CHECK TABLE语句来检查表是否损坏,尽管CHECK
TABLE自然无法检测到任何可能的损坏类型。
在某些情况下,明显的数据库页面损坏实际上是由于操作系统损坏其自己的文件缓存,并且磁盘上的数据可能没有问题。最好先尝试重新启动计算机。这样做可能会消除似乎是数据库页面损坏的错误。如果由于InnoDB一致性问题,MySQL仍然无法启动,请参见
第14.21.2节“强制InnoDB恢复”以获取以恢复模式启动实例的步骤,这允许您转储数据。
要从MySQL服务器崩溃中恢复,唯一的要求是重新启动MySQL服务器。InnoDB
自动检查日志并执行数据库前滚至当前。InnoDB自动回滚崩溃时出现的未提交事务。在恢复过程中,mysqld
显示类似如下的输出:
InnoDB:日志扫描通过检查点lsn 369163704 InnoDB:执行恢复:扫描到日志序列号374340608 InnoDB:执行恢复:扫描到日志序列号379583488 InnoDB:执行恢复:扫描到日志序列号384826368 InnoDB:执行恢复:扫描到日志序列号390069248 InnoDB:执行恢复:扫描至记录序列号395312128 InnoDB:执行恢复:扫描到日志序列号400555008 InnoDB:执行恢复:扫描到日志序列号405797888 InnoDB:执行恢复:扫描到日志序列号411040768 InnoDB:执行恢复:扫描至记录序列号414724794 InnoDB:数据库没有正常关闭! InnoDB:启动崩溃恢复。 InnoDB:1个必须回滚或清理的事务 总共需要518425行操作才能撤消 InnoDB:Trx id counter是1792 InnoDB:开始对数据库应用一批日志记录... InnoDB:百分比进展:0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 InnoDB:应用批处理完成 ... InnoDB:从后台开始回滚未提交的事务 InnoDB:回滚trx,id为1511,518425行以撤消 ... InnoDB:等待清洗开始 InnoDB:5.7.18开始; 日志序列号414724794 ... ./mysqld:准备好连接。
InnoDB
崩溃恢复
包括几个步骤:
表空间发现
表空间发现是InnoDB用于标识需要重做日志应用程序的表空间的过程
。请参阅
崩溃恢复期间的表空间发现。
重做日志应用程序
重做日志应用程序在初始化期间执行,然后接受任何连接。如果
在关闭或崩溃时将所有更改从缓冲池刷新
到表空间
(ibdata*和*.ibd文件),则会跳过重做日志应用程序。InnoDB如果重做日志文件在启动时丢失,也会跳过重做日志应用程序。
不建议删除重做日志以加速恢复,即使可以接受某些数据丢失。只有在干净关闭后才能考虑删除重做日志,并将其
innodb_fast_shutdown设置为
0或1。
有关InnoDB用于识别需要重做日志应用程序的表空间的过程的信息
,请参阅
崩溃恢复过程中的表空间发现。
不完整的事务是在崩溃或快速关闭时处于活动状态的任何事务 。根据服务器负载,回滚未完成事务所花费的时间可能是事务处于活动状态之前的活动时间的三到四倍。
您无法取消正在回滚的交易。在极端情况下,回滚事务预计需要很长时间时,InnoDB以
innodb_force_recovery
设置3或更高开始可能会更快。请参见
第14.21.2节“强制InnoDB恢复”。
更改缓冲区 合并
因为将索引页读入缓冲池 ,所以将更改缓冲区(系统表空间的一部分)中的更改应用于 辅助索引的叶页。
删除对活动事务不再可见的删除标记的记录。
重做日志应用程序后面的步骤不取决于重做日志(除了记录写入操作之外),并且与正常处理并行执行。其中,只有回滚未完成的交易对于崩溃恢复是特别的。插入缓冲区合并和清除在正常处理期间执行。
重做日志应用程序后,InnoDB尽可能早地尝试接受连接,以减少停机时间。作为崩溃恢复的一部分,InnoDB回滚XA
PREPARE在服务器崩溃时未提交或处于状态的事务。回滚由后台线程执行,与新连接的事务并行执行。在回滚操作完成之前,新连接可能会遇到与已恢复事务的锁定冲突。
在大多数情况下,即使MySQL服务器在繁重的活动中意外中止,恢复过程也会自动进行,并且不需要DBA的任何操作。如果硬件故障或严重的系统错误损坏了
InnoDB数据,MySQL可能会拒绝启动。在这种情况下,请参见第14.21.2节“强制InnoDB恢复”。
有关二进制日志和
InnoDB崩溃恢复的信息,请参见
第5.4.4节“二进制日志”。
如果在恢复过程中InnoDB遇到自上次检查点以来写入的重做日志,则必须将重做日志应用于受影响的表空间。在恢复过程中识别受影响的表空间的过程称为
表空间发现。
通过扫描从最后一个检查点到日志末尾的重做日志,可以执行表空间发现,以查找
MLOG_FILE_NAME修改表空间页面时写入的记录。一条
MLOG_FILE_NAME记录包含表空间空间ID和文件名。
在启动时,InnoDB打开系统表空间和重做日志。如果自上次检查点以来写入了重做日志记录,则会根据MLOG_FILE_NAME记录打开受影响的表空间文件。
MLOG_FILE_NAME 记录是针对所有持久表空间类型编写的,包括文件每表表空间,常规表空间,系统表空间和撤消日志表空间。
基于重做日志的发现具有以下特征:
仅*.ibd访问自上一个检查点以来修改的表空间文件。
当应用重做日志时*.ibd,未附加到InnoDB实例的
表空间文件将被忽略。
如果MLOG_FILE_NAME系统表空间的记录与影响系统表空间数据文件名的服务器配置不匹配,则在应用重做日志之前,恢复将失败,并显示错误。
如果日志的扫描部分中引用的表空间文件丢失,则启动将被拒绝。
*.ibd
只有MLOG_FILE_DELETE在日志中存在文件删除重做日志记录()时,才会忽略
丢失的表空间文件的重做日志。例如,表重命名失败可能导致没有记录的
“ 丢失 ” *.ibd文件MLOG_FILE_DELETE。在这种情况下,您可以手动重命名表空间文件并重新启动崩溃恢复,也可以使用该innodb_force_recovery
选项以恢复模式重新启动服务器
。*.ibd当服务器在恢复模式下启动时,忽略丢失的文件。
在MySQL 5.7中引入的基于重做日志的发现替代了早期MySQL版本中使用的目录扫描,以构建应用重做日志所需的“ 空间ID到表空间文件名 ”映射。
MySQL的复制适用InnoDB于MyISAM表格。还有可能以从机上的存储引擎与主机上的原始存储引擎不相同的方式使用复制。例如,可以InnoDB将对主服务器上的MyISAM表的修改复制到从服务器
上的
表上。有关更多信息,请参见第16.3.3节“在不同的主存储引擎和从属存储引擎中使用复制”。
有关为主站设置新从站的信息,请参见 第16.1.2.5节“设置复制从站”以及 第16.1.2.4节“为数据快照选择方法”。要创建新的从服务器而不关闭主服务器或现有的从服务器,请使用 MySQL企业备份产品。
在主服务器上失败的事务根本不影响复制。MySQL复制基于MySQL写入修改数据的SQL语句的二进制日志。失败的事务(例如,由于外键违规或因为它被回退)不会写入二进制日志,因此它不会发送到从属设备。请参见第13.3.1节“START TRANSACTION,COMMIT和ROLLBACK语法”。
复制和CASCADE。 只有当共享外键关系的表在主控和从属上使用
时,主控InnoDB上的表的
级联动作才会复制到从控制器上。无论您是使用基于语句的还是基于行的复制,情况都是如此。假设您已经开始复制,然后使用以下语句在主服务器上创建两个表
:
InnoDBCREATE TABLE
CREATE TABLE fc1(
我INT主键,
j INT
)ENGINE = InnoDB;
CREATE TABLE fc2(
m INT主键,
INT,
外键ni(n)参考文献fc1(i)
ON DELETE CASCADE
)ENGINE = InnoDB;
假设从站没有InnoDB
启用支持。如果是这种情况,则创建从属表上的表,但它们使用MyISAM存储引擎,并FOREIGN KEY忽略该选项。现在我们在主表中插入一些行:
高手>INSERT INTO fc1 VALUES (1, 1), (2, 2);查询OK,2行受影响(0.09秒) 记录:2重复:0警告:0 高手>INSERT INTO fc2 VALUES (1, 1), (2, 2), (3, 1);查询OK,3行受影响(0.19秒) 记录:3重复:0警告:0
此时,在主设备和从设备上,表格
fc1包含2行,表格
fc2包含3行,如下所示:
高手>SELECT * FROM fc1;+ --- + ------ + | 我| j | + --- + ------ + | 1 | 1 | | 2 | 2 | + --- + ------ + 设置2行(0.00秒) 高手>SELECT * FROM fc2;+ --- + ------ + | m | n | + --- + ------ + | 1 | 1 | | 2 | 2 | | 3 | 1 | + --- + ------ + 设置3行(0.00秒) 从>SELECT * FROM fc1;+ --- + ------ + | 我| j | + --- + ------ + | 1 | 1 | | 2 | 2 | + --- + ------ + 设置2行(0.00秒) 从>SELECT * FROM fc2;+ --- + ------ + | m | n | + --- + ------ + | 1 | 1 | | 2 | 2 | | 3 | 1 | + --- + ------ + 设置3行(0.00秒)
现在假设你DELETE在master上执行以下
语句:
高手> DELETE FROM fc1 WHERE i=1;
查询OK,1行受影响(0.09秒)
由于级联,fc2主站上的表现在只包含1行:
高手> SELECT * FROM fc2;
+ --- + --- +
| m | n |
+ --- + --- +
| 2 | 2 |
+ --- + --- +
一排(0.00秒)
但是,级联不会在从属设备上传播,因为在从属设备上DELETE用于
fc1从中删除行fc2。奴隶的副本fc2仍然包含最初插入的所有行:
从> SELECT * FROM fc2;
+ --- + --- +
| m | n |
+ --- + --- +
| 1 | 1 |
| 3 | 1 |
| 2 | 2 |
+ --- + --- +
设置3行(0.00秒)
这种差异是由于级联删除是由InnoDB存储引擎内部处理的,这意味着没有任何更改被记录。
的InnoDB 分布式缓存插件(daemon_memcached)提供了一个集成
的memcached守护程序自动存储和检索从数据InnoDB表,把MySQL服务器到快速“ 键值存储 ”。您可以使用简单的get,set和incr操作来避免与SQL解析和构建查询优化计划相关的性能开销,而
不是使用SQL来制定查询
。InnoDB为了方便,复杂的查询,批量操作以及传统数据库软件的其他优势,您还可以通过SQL 访问相同的
表。
这个“ NoSQL样式 ”接口使用
memcached API来加速数据库操作,让它InnoDB使用缓冲池机制来处理内存缓存
。通过修改的数据分布式缓存操作,诸如
add,set以及
incr被存储到磁盘,在
InnoDB表中。的组合
分布式缓存的简单性和
InnoDB可靠性和一致性提供两全其美的用户,如在解释
第14.20.1“InnoDB的的好处的memcached插件”。有关架构概述,请参阅第14.20.2节“InnoDB memcached体系结构”。
本节概述了daemon_memcached插件的优点
。InnoDB表和memcached的组合
提供了优于单独使用的优势。
直接访问InnoDB存储引擎避免了SQL的解析和计划开销。
在与MySQL服务器相同的进程空间中 运行memcached避免了来回传递请求的网络开销。
使用memcached协议编写的数据透明地写入InnoDB
表中,而无需通过MySQL SQL层。在更新非关键数据时,您可以控制写入频率以实现更高的原始性能。
通过memcached
协议请求的数据可以透明地从InnoDB表中查询
,而无需通过MySQL SQL层。
随后对相同数据的请求由
InnoDB缓冲池提供。缓冲池处理内存中的缓存。您可以使用InnoDB
配置选项来调整数据密集型操作的性能。
数据可以是非结构化或结构化的,这取决于应用程序的类型。您可以为数据创建新表,或使用现有表。
InnoDB可以处理将多个列值组合和分解为单个
memcached项目值,从而减少应用程序中所需的字符串解析和串联量。例如,可以将字符串值存储
2|4|6|8在memcached
缓存中,并InnoDB根据分隔符分割值,然后将结果存储在四个数字列中。
内存和磁盘之间的传输是自动处理的,简化了应用程序逻辑。
数据存储在MySQL数据库中以防止崩溃,中断和损坏。
您可以InnoDB通过SQL 访问基础表以进行报告,分析,即席查询,批量加载,多步事务计算,集合操作(如联合和交集)以及其他适合SQL表现力和灵活性的操作。
您可以通过将主服务器daemon_memcached上的插件
与MySQL复制结合使用来确保高可用性
。
memcached与MySQL
的集成提供了一种使内存中的数据持久化的方法,因此您可以将它用于更重要的数据类型。您可以使用更多
add,incr在您的应用程序,以及类似的写操作,而不用担心数据丢失。您可以停止并启动
memcached服务器,而不会丢失对缓存数据的更新。为防止意外中断,您可以利用InnoDB崩溃恢复,复制和备份功能。
该方法InnoDB确实快速
的主键查找是天作之合memcached的单项查询。daemon_memcached插件使用的直接,低级数据库访问路径对于键值查找而言比等效的SQL查询效率更高。
memcached 的序列化功能可以将复杂的数据结构,二进制文件甚至代码块转换为可存储的字符串,提供了一种简单的方法将这些对象存入数据库。
因为你可以通过SQL访问底层数据,可以生成报告,在多个搜索键或更新,并调用功能,如AVG()与
MAX()上memcached的数据。所有这些操作本身使用memcached都很昂贵或复杂
。
您不需要在启动时手动将数据加载到
memcached中。由于应用程序请求特定的键,因此会自动从数据库中检索值,并使用InnoDB
缓冲池将其缓存到内存中
。
因为memcached消耗的CPU相对较少,并且其内存占用容易控制,所以它可以在同一系统上与MySQL实例一起轻松运行。
由于数据一致性是由用于常规InnoDB表的机制执行的,因此您不必担心失效 memcached数据或备用逻辑在缺少密钥的情况下查询数据库。
该 InnoDB 分布式缓存插件实现的memcached作为访问一个MySQL插件守护程序InnoDB直接存储引擎,绕过MySQL的SQL层。
下图说明了daemon_memcached与SQL相比,应用程序通过插件访问数据的方式。
该功能daemon_memcached插件:
memcached作为 mysqld的守护进程插件 。这两个 mysqld和 memcached的在同一个进程空间中运行,具有非常低的延迟对数据的访问。
直接访问InnoDB表,绕过SQL解析器,优化器甚至Handler API层。
标准memcached协议,包括基于文本的协议和二进制协议。该
daemon_memcached插件通过memcapable
命令的所有55个兼容性测试。
多列支持。您可以将多个列映射到 “键/值存储值 ”部分,列值由用户指定的分隔符分隔。
默认情况下,memcached协议用于直接读取和写入数据InnoDB,让MySQL使用InnoDB
缓冲池管理内存中的缓存
。默认设置表示高可靠性和数据库应用程序最少意外的组合。例如,默认设置可避免数据库端的未提交数据或返回的陈旧数据
memcached get请求。
高级用户可以将系统配置为传统的
memcached服务器,所有数据仅在memcached引擎中缓存(内存缓存),或者结合使用
“ memcached引擎 ”(内存缓存)和InnoDB
memcached引擎(InnoDB
作为后端持久性存储)。
控制多久数据来回传递之间
InnoDB和memcached的
通过操作
innodb_api_bk_commit_interval,
daemon_memcached_r_batch_size以及
daemon_memcached_w_batch_size
配置选项。批量大小选项的默认值为1以实现最大可靠性。
通过
配置参数
指定memcached选项的功能
daemon_memcached_option。例如,您可以更改memcached侦听的端口,减少同时连接的最大数量,更改某个键/值对的最大内存大小,或为错误日志启用调试消息。
的innodb_api_trx_level
配置选项控制事务
隔离级别上通过处理的查询分布式缓存。尽管
memcached没有事务的概念
,但您可以使用此选项来控制memcached多久
可以看到由daemon_memcached插件使用的表上发出的SQL语句导致的更改
。默认情况下,
innodb_api_trx_level设置为READ UNCOMMITTED。
该innodb_api_enable_mdl
选项可用于在MySQL级锁定表,以便映射表不能通过SQL接口由DDL删除或更改
。没有锁定,表可以从MySQL层中删除,但保存在InnoDB存储中,直到
memcached或其他用户停止使用它。“ MDL ”代表“ 元数据锁定 ”。
您可能已经熟悉使用
memcached的使用MySQL,如在
使用MySQL与memcached的。本节介绍集成的InnoDB
memcached插件的功能与传统的不同
memcached。
安装:Memcached库随MySQL服务器一起提供,使安装和设置相对简单。安装包括运行
innodb_memcached_config.sql脚本demo_test为memcached创建一个表
来使用,发布一个
INSTALL PLUGIN语句来启用该daemon_memcached插件,并将所需的memcached选项添加到MySQL配置文件或启动脚本中。您仍然可以安装传统的memcached
发行版,以使用其他实用程序,例如
memcp,memcat和
memcapable。
为了与传统的memcached进行比较 ,请参阅 安装memcached。
部署:使用传统的memcached,通常会运行大量的低容量
memcached服务器。daemon_memcached然而,插件的典型部署涉及少量已经运行MySQL的中等或高性能服务器。这种配置的好处是提高单个数据库服务器的效率,而不是利用未使用的内存或在大量服务器上分布查找。在默认配置中,memcached只使用很少的内存
,而内存中的查找则由InnoDB
缓冲池提供,它会自动缓存最近使用频繁使用的数据。和传统的MySQL服务器实例一样,保持innodb_buffer_pool_size
配置选项的值
尽可能高(不会在操作系统级别导致分页),以便在内存中执行尽可能多的工作。
为了与传统的memcached进行比较 ,请参阅 memcached部署。
到期:默认情况下(即使用
innodb_only缓存策略),InnoDB表中的最新数据总是被返回,因此到期选项没有实际影响。如果您将缓存策略更改为caching
或cache-only,则过期选项照常工作,但如果在基础表中从内存高速缓存到期之前更新了所请求的数据,则所请求的数据可能过时。
为了与传统的memcached进行比较 ,请参阅 Data Expiry。
命名空间:memcached就像一个大型的目录,在这个目录下,你可以使用前缀和后缀给文件精心制作名称,以防止文件发生冲突。该
daemon_memcached插件允许您使用类似的密钥命名约定,并增加一个。格式中的键名
。
被解码以使用来自
表格的映射数据来引用特定的表格。该@@table_id.keytable_idinnodb_memcache.containerskey被查找或写入到指定的表。
该@@符号只适用于个别呼叫get,add和
set功能,而不是其他如
incr或delete。要为会话中的后续memcached操作指定默认表,
get请使用@@带有符号的表示法
执行请求
但没有键部分。例如:
table_id
获取@@table_id
随后get,set,
incr,delete,等操作使用由指定的表
中table_idinnodb_memcache.containers.name
列。
为了与传统的memcached进行比较 ,请参阅 使用命名空间。
散列和分发:使用innodb_only高速缓存策略的默认配置适用于所有服务器(例如一组复制从服务器)上都有所有数据的传统部署配置。
如果您物理分割数据(如分片配置),则可以在运行daemon_memcached插件的多台计算机上拆分数据,并使用传统的memcached哈希机制将请求路由到特定的计算机。在MySQL方面,您通常会让所有数据按add请求插入
到
memcached中以便将适当的值存储在相应服务器上的数据库中。
为了与传统的memcached进行比较 ,请参阅 memcached散列/分布类型。
内存使用情况:缺省情况下(使用
innodb_only缓存策略),
memcached协议会向InnoDB表传递信息,InnoDB缓冲池处理内存查找,而不是memcached内存使用量增长和收缩。memcached端使用的内存相对较少。
如果将缓存策略切换为
caching或cache-only,则适用memcached内存使用的正常规则。memcached数据值的内存按照“ slabs ”分配。您可以控制用于memcached的平板大小和最大内存
。
无论使用哪种方式,您都可以daemon_memcached使用熟悉的统计系统监视和排除插件问题
,例如,通过标准协议通过Telnet会话访问
插件
。该daemon_memcached插件不包含额外的实用程序
。您可以使用该
memcached-tool
脚本安装完整的memcached
分发。
为了与传统的比较 memcached的,见 内内存分配的memcached。
线程使用情况:MySQL线程和memcached 线程共存于同一台服务器上。操作系统对线程施加的限制适用于线程总数。
为了与传统的memcached进行比较 ,请参阅 memcached线程支持。
日志的使用:由于memcached的守护程序同时运行MySQL服务器和写入
stderr的-v,
-vv和-vvv选项日志输出写入MySQL的
错误日志。
为了与传统的memcached进行比较 ,请参阅 memcached Logs。
memcached的操作:熟悉
memcached的操作,例如
get,set,
add,和delete可用。序列化(即,表示复杂数据结构的确切字符串格式)取决于语言界面。
为了与传统的memcached进行比较 ,请参阅 基本memcached操作。
使用memcached作为MySQL前端:这是InnoDB
memcached插件的主要目的。集成的
memcached守护进程提高了应用程序的性能,并InnoDB处理内存和磁盘之间的数据传输,从而简化了应用程序逻辑。
为了与传统的memcached进行比较 ,请参阅 将memcached用作MySQL缓存层。
实用程序:MySQL服务器包含该libmemcached库,但不包括
其他命令行实用程序。要使用诸如
memcp,memcat和
memcapable命令之类的命令,请安装完整的
memcached分发。当
memrm和memflush
从缓存中删除项目时,项目也会从基础InnoDB表中删除。
为了与传统的memcached进行比较 ,请参阅 libmemcached命令行实用程序。
编程接口:您可以daemon_memcached使用所有支持的语言通过插件访问MySQL服务器:
C和C ++,
Java,
Perl,
Python,
PHP和
Ruby。像传统的memcached服务器一样指定服务器主机名和端口
。默认情况下,
daemon_memcached插件在端口上侦听
11211。您可以使用
文本和二进制协议。您可以自定义
行为
的运行时的 memcached函数。序列化(即,表示复杂数据结构的确切字符串格式)取决于语言界面。
为了与传统的memcached进行比较 ,请参阅 开发memcached应用程序。
常见问题:MySQL对传统的memcached有广泛的FAQ 。除了使用InnoDB
表格作为memcached
数据的存储介质之外,常见问题解答最适用,这意味着您可以将memcached用于比以前更多的写入密集型应用程序,而不是只读缓存。
请参阅memcached FAQ。
本节介绍如何daemon_memcached在MySQL服务器上设置
插件。由于memcached守护进程与MySQL服务器紧密集成以避免网络流量并将延迟降至最低,因此您在使用此功能的每个MySQL实例上执行此过程。
在设置daemon_memcached
插件之前,请参阅第14.20.4节“InnoDB memcached插件的安全注意事项”以了解防止未授权访问所需的安全步骤。
该daemon_memcached插件仅在Linux,Solaris和OS X平台上受支持。其他操作系统不受支持。
从源代码构建MySQL时,必须使用
-DWITH_INNODB_MEMCACHED=ON。这个构建选项会在MySQL插件目录(plugin_dir)中生成两个运行daemon_memcached
插件所需的共享库:
libmemcached.so:MySQL 的
memcached守护进程插件。
innodb_engine.so:一个memcached的
InnoDBAPI插件
。
libevent 必须安装。
如果您没有从源代码构建MySQL,则该
libevent库不包含在您的安装中。使用适用于您的操作系统的安装方法安装libevent
1.4.12或更高版本。例如,根据操作系统,您可以使用apt-get,
yum或port
install。例如,在Ubuntu Linux上,使用:
sudo apt-get install libevent-dev
如果您从源代码版本安装MySQL,则
libevent1.4.12将与该软件包捆绑在一起,并位于MySQL源代码目录的顶层。如果您使用捆绑版本
libevent,则无需执行任何操作。如果要使用本地系统版本
libevent,则必须使用-DWITH_LIBEVENT设置为system或
的构建选项构建MySQL yes。
通过运行位于的
配置脚本
daemon_memcached来
配置插件,以便它可以与InnoDB表交互。该脚本安装
有三个需要的表数据库(,
,和
)。它还将示例表安装
在
数据库中。
innodb_memcached_config.sqlMYSQL_HOME/shareinnodb_memcachecache_policiesconfig_optionscontainersdemo_testtest
MySQL的> source MYSQL_HOME/share/innodb_memcached_config.sql
运行innodb_memcached_config.sql
脚本是一次性操作。如果稍后卸载并重新安装该daemon_memcached插件,表格将保留在原位
。
mysql>USE innodb_memcache;mysql>SHOW TABLES;+ --------------------------- + | Tables_in_innodb_memcache | + --------------------------- + | cache_policies | | config_options | | 容器| + --------------------------- + mysql>USE test;mysql>SHOW TABLES;+ ---------------- + | Tables_in_test | + ---------------- + | demo_test | + ---------------- +
在这些表格中,
innodb_memcache.containers表格是最重要的。containers
表中的条目提供了对InnoDB表格列的映射。InnoDB与daemon_memcached插件一起使用的每个表都
需要在containers表中输入一个条目。
该innodb_memcached_config.sql脚本在containers
表格中插入单个条目,为表格提供映射
demo_test。它还将一行数据插入demo_test表中。这些数据可让您在安装完成后立即验证安装。
MySQL的>SELECT * FROM innodb_memcache.containers\G*************************** 1. row ******************** ******* 名称:aaa db_schema:测试 db_table:demo_test key_columns:c1 value_columns:c2 标志:c3 cas_column:c4 expire_time_column:c5 unique_idx_name_on_key:PRIMARY MySQL的>SELECT * FROM test.demo_test;+ ---- + ------------------ + ------ + ------ + ------ + | c1 | c2 | c3 | c4 | c5 | + ---- + ------------------ + ------ + ------ + ------ + | AA | HELLO,HELLO | 8 | 0 | 0 | + ---- + ------------------ + ------ + ------ + ------ +
有关innodb_memcache表和
demo_test示例表的更多信息
,请参见
第14.20.7节“InnoDB memcached插件内部”。
daemon_memcached通过运行INSTALL PLUGIN
语句来
激活插件:
MySQL的> INSTALL PLUGIN daemon_memcached soname "libmemcached.so";
一旦插件安装完成,每次MySQL服务器重新启动时它都会自动激活。
要验证daemon_memcached插件设置,请使用telnet会话发出
memcached命令。默认情况下,
memcached守护程序在端口11211上侦听。
从test.demo_test
表中检索数据。demo_test表格中的单行数据
具有键值
AA。
telnet localhost 11211尝试127.0.0.1 ... 连接到本地主机。 转义字符是'^]'。get AA价值AA 8 12 你好你好 结束
使用set命令插入数据。
set BB 10 0 16GOODBYE, GOODBYESTORED
哪里:
set 是存储值的命令
BB 是关键
10是该行动的一面旗帜; 被memcached忽略,但可能被客户用来指示任何类型的信息; 指定0是否未使用
0是到期时间(TTL); 指定0是否未使用
16 是所提供的值块的字节长度
GOODBYE, GOODBYE 是存储的值
通过连接到MySQL服务器并查询test.demo_test表,验证插入的数据是否存储在MySQL
中。
MySQL的> SELECT * FROM test.demo_test;
+ ---- + ------------------ + ------ + ------ + ------ +
| c1 | c2 | c3 | c4 | c5 |
+ ---- + ------------------ + ------ + ------ + ------ +
| AA | HELLO,HELLO | 8 | 0 | 0 |
| BB | GOODBYE,GOODBYE | 10 | 1 | 0 |
+ ---- + ------------------ + ------ + ------ + ------ +
返回到Telnet会话并使用密钥检索先前插入的数据BB。
get BB价值BB 10 16 GOODBYE,GOODBYE 结束quit
如果您关闭了也关闭集成的memcached服务器的MySQL服务器,则进一步访问memcached数据的尝试会失败,并显示连接错误。通常情况下,memcached
数据在这一点上也会消失,当memcached重新启动时,您需要应用程序逻辑将数据加载回内存
。但是,
InnoDB memcached插件会为您自动执行此过程。
当您重新启动MySQL时,get操作会再次返回您在先前的memcached会话中存储的键/值对
。当请求一个关键字并且关联的值尚未存在于内存高速缓存中时,该值将自动从MySQL test.demo_test表中查询
。
这个例子展示了如何InnoDB用daemon_memcached插件设置你自己的
表格
。
创建一个InnoDB表。该表必须具有唯一索引的键列。城市表的关键列是city_id,它被定义为主键。该表还必须包括列
flags,cas和
expiry值。可能有一个或多个值列。该city表有三个值列(name,
state,country)。
对于列名,没有特别的要求,因为有效的映射被添加到
innodb_memcache.containers表中。
mysql>
)CREATE TABLE city (
city_id VARCHAR(32),
name VARCHAR(1024),
state VARCHAR(1024),
country VARCHAR(1024),
flags INT,
cas BIGINT UNSIGNED,
expiry INT,
primary key(city_id)ENGINE=InnoDB;
向innodb_memcache.containers表中添加一个条目,
以便daemon_memcached插件知道如何访问InnoDB表。该条目必须满足innodb_memcache.containers
表格定义。有关每个字段的说明,请参见
第14.20.7节“InnoDB memcached插件内部”。
MySQL的> DESCRIBE innodb_memcache.containers;
+ ------------------------ + -------------- + ------ + - --- + --------- + ------- +
| 字段| 类型| 空| Key | 默认| 额外|
+ ------------------------ + -------------- + ------ + - --- + --------- + ------- +
| 名称| varchar(50)| NO | PRI | NULL | |
| db_schema | varchar(250)| NO | | NULL | |
| db_table | varchar(250)| NO | | NULL | |
| key_columns | varchar(250)| NO | | NULL | |
| value_columns | varchar(250)| 是| | NULL | |
| flags | varchar(250)| NO | | 0 | |
| cas_column | varchar(250)| 是| | NULL | |
| expire_time_column | varchar(250)| 是| | NULL | |
| unique_idx_name_on_key | varchar(250)| NO | | NULL | |
+ ------------------------ + -------------- + ------ + - --- + --------- + ------- +
在innodb_memcache.containers全市表表项被定义为:
MySQL的>INSERT INTO `innodb_memcache`.`containers` (`name`, `db_schema`, `db_table`, `key_columns`, `value_columns`,`flags`, `cas_column`, `expire_time_column`, `unique_idx_name_on_key`)VALUES ('default', 'test', 'city', 'city_id', 'name|state|country','flags','cas','expiry','PRIMARY');
default是为该containers.name列指定的,将该
city表配置为InnoDB与该daemon_memcached插件一起使用的默认
表
。
多InnoDB表列(name,state,
country)映射到
containers.value_columns使用
“ | “分隔符。
的flags,
cas_column以及
expire_time_column该领域
innodb_memcache.containers表通常不使用的应用程序显著
daemon_memcached插件。但是,每个指定的InnoDB表格列都是必需的。插入数据时,0为这些列指定
它们是否未使用。
更新
innodb_memcache.containers表格后,重新启动daemon_memcache插件以应用更改。
MySQL的>UNINSTALL PLUGIN daemon_memcached;MySQL的>INSTALL PLUGIN daemon_memcached soname "libmemcached.so";
使用telnet,city
使用memcached
set命令将数据插入表中。
telnet localhost 11211尝试127.0.0.1 ... 连接到本地主机。 转义字符是'^]'。set B 0 0 22BANGALORE|BANGALORE|INSTORED
使用MySQL,查询test.city表格以验证您插入的数据是否已存储。
MySQL的> SELECT * FROM test.city;
+ --------- + ----------- ----------- + + --------- + ----- - + ------ + -------- +
| city_id | 名称| 状态| 国家| flags | cas | 到期|
+ --------- + ----------- ----------- + + --------- + ----- - + ------ + -------- +
| B | BANGALORE | BANGALORE | IN | 0 | 3 | 0 |
+ --------- + ----------- ----------- + + --------- + ----- - + ------ + -------- +
使用MySQL,将附加数据插入
test.city表中。
mysql>INSERT INTO city VALUES ('C','CHENNAI','TAMIL NADU','IN', 0, 0 ,0);mysql>INSERT INTO city VALUES ('D','DELHI','DELHI','IN', 0, 0, 0);mysql>INSERT INTO city VALUES ('H','HYDERABAD','TELANGANA','IN', 0, 0, 0);mysql>INSERT INTO city VALUES ('M','MUMBAI','MAHARASHTRA','IN', 0, 0, 0);
建议您0为“ flags,
cas_column”和“
expire_time_column字段” 指定值(
如果它们未被使用)。
使用telnet,发出一个memcached
get命令来检索你使用MySQL插入的数据。
get H
值H 0 22
海得拉巴|特兰伽纳| IN
结束
传统memcached配置选项可以在
配置参数的参数中编码的MySQL配置文件或
mysqld启动字符串中
daemon_memcached_option指定。memcached
配置选项在加载插件时生效,每次启动MySQL服务器时都会发生这种情况。
例如,要使memcached在端口11222而不是默认端口11211上侦听,请指定
-p11222为daemon_memcached_option
配置选项的参数
:
mysqld .... --daemon_memcached_option =“ - p11222”
其他memcached选项可以在daemon_memcached_option字符串中编码
。例如,可以指定选项以减少同时连接的最大数量,更改键/值对的最大内存大小,或为错误日志启用调试消息等等。
还有特定于该daemon_memcached插件的配置选项
。这些包括:
daemon_memcached_engine_lib_name:指定实现InnoDB memcached
插件的共享库
。默认设置是
innodb_engine.so。
daemon_memcached_engine_lib_path:包含实现InnoDB
memcached插件的共享库的目录的路径。缺省值为NULL,表示插件目录。
daemon_memcached_r_batch_size:定义读操作(get)的批量落实大小。它指定发生提交之后的memcached读取操作
的数量
。
默认情况下设置为1,以便每个
请求都可以访问表中最近提交的数据
,不管数据是通过memcached还是通过SQL 更新的。当该值大于1时,读取操作的计数器随每次调用而增加。一个
调用重置读取和写入计数器。
daemon_memcached_r_batch_sizegetInnoDBgetflush_all
daemon_memcached_w_batch_size:定义批提交大小写操作(set,replace,
append,prepend,
incr,decr,等)。
daemon_memcached_w_batch_size
默认情况下设置为1,以便在发生中断时不丢失未提交的数据,并且使得基础表上的SQL查询访问最近的数据。当该值大于1时,用于写入操作的计数器被递增为每个add,
set,incr,
decr,和delete调用。一个flush_all调用重置读取和写入计数器。
默认情况下,您不需要修改
daemon_memcached_engine_lib_name
或
daemon_memcached_engine_lib_path。例如,如果您想要为memcached使用不同的存储引擎
(例如NDB memcached引擎),则可以配置这些选项。
daemon_memcached插件配置参数可以在MySQL配置文件或mysqld启动字符串中指定。它们在加载daemon_memcached插件时生效。
在更改daemon_memcached
插件配置时,请重新加载插件以应用更改。为此,请发出以下声明:
MySQL的>UNINSTALL PLUGIN daemon_memcached;MySQL的>INSTALL PLUGIN daemon_memcached soname "libmemcached.so";
配置设置,所需表格和数据在插件重新启动时被保留。
有关启用和禁用插件的更多信息,请参见第5.5.1节“安装和卸载插件”。
daemon_memcached在生产服务器上
部署插件之前,或者在MySQL实例包含敏感数据的情况下甚至在测试服务器上部署插件之前,请先参考此部分
。
由于默认情况下memcached不使用身份验证机制,并且可选SASL身份验证不像传统DBMS安全措施那样强壮,所以仅在使用该daemon_memcached插件的MySQL实例中保留非敏感数据,并隔离使用此配置的任何服务器来自潜在的入侵者。不要允许memcached从Internet访问这些服务器; 只允许在防火墙内部网中访问,理想情况下是从您可以限制其成员资格的子网访问。
SASL支持提供了通过memcached客户端保护您的MySQL数据库免受未经身份验证访问的能力
。本节介绍如何使用daemon_memcached
插件启用SASL 。这些步骤与为传统的memcached
服务器启用SASL所执行的步骤几乎完全相同。
SASL代表“ 简单认证和安全层 ”,这是为基于连接的协议添加认证支持的标准。memcached在版本1.4.3中增加了SASL支持。
SASL认证仅支持二进制协议。
memcached客户端只能访问在
InnoDB表中注册的
innodb_memcache.containers表。尽管DBA可以对这些表设置访问限制,但无法控制通过 memcached应用程序访问。出于这个原因,SASL支持被提供来控制对InnoDB与daemon_memcached插件关联的表的访问。
以下部分显示如何构建,启用和测试支持SASL的daemon_memcached插件。
默认情况下,支持SASL的daemon_memcached
插件不包含在MySQL发布包中,因为支持SASL的daemon_memcached插件需要使用SASL库构建memcached。要启用SASL支持,请下载MySQL源并daemon_memcached在下载SASL库后重新
构建插件:
安装SASL开发和实用程序库。例如,在Ubuntu上,使用apt-get获取库:
sudo apt-get -f install libsasl2-2 sasl2-bin libsasl2-2 libsasl2-dev libsasl2-modules
daemon_memcached通过添加ENABLE_MEMCACHED_SASL=1到cmake选项来
构建具有SASL功能的插件共享库
。
memcached还提供简单的明文密码支持,这有助于测试。要启用简单的明文密码支持,请指定ENABLE_MEMCACHED_SASL_PWDB=1
cmake选项。
总之,添加以下三个cmake 选项:
cmake ... -DWITH_INNODB_MEMCACHED = 1 -DENABLE_MEMCACHED_SASL = 1 -DENABLE_MEMCACHED_SASL_PWDB = 1
daemon_memcached如第14.20.3节“设置InnoDB memcached插件”中所述
安装该插件。
配置用户名和密码文件。(这个例子使用 memcached简单明文密码支持。)
在一个文件中,创建一个名为user
testname并定义密码为
testpasswd:
echo“testname:testpasswd :::::::”> / home / jy / memcached-sasl-db
配置MEMCACHED_SASL_PWDB
环境变量以通知
memcached用户名和密码文件:
导出MEMCACHED_SASL_PWDB = / home / jy / memcached-sasl-db
通知memcached使用明文密码:
echo“mech_list:plain”> /home/jy/work2/msasl/clients/memcached.conf 导出SASL_CONF_PATH = / home / jy / work2 / msasl / clients
通过
配置参数中编码的memcached -S选项
重新启动MySQL服务器来启用SASL
daemon_memcached_option:
mysqld ... --daemon_memcached_option =“ - S”
要测试设置,请使用支持SASL的客户端,如 启用SASL的libmemcached。
memcp --servers = localhost:11211 --binary --username = testname --password =passwordmyfile.txt memcat --servers = localhost:11211 --binary --username = testname --password =passwordmyfile.txt
如果您指定了错误的用户名或密码,则该操作将被拒绝并显示一条memcache error
AUTHENTICATION FAILURE消息。在这种情况下,请检查memcached-sasl-db文件中设置的明文密码,
以验证您提供的凭据是否正确。
还有其他方法可以用memcached测试SASL认证 ,但上述方法是最直接的。
通常,为InnoDB memcached插件编写应用程序
需要一定程度的重写或修改使用MySQL或memcached API的现有代码。
使用daemon_memcached插件,而不是运行在低功率机器上的许多传统memcached服务器,您拥有与MySQL服务器相同数量的
memcached服务器,运行在相对高性能的机器上,并具有大量的磁盘存储和内存。您可能会重用一些与memcached API 配合使用的现有代码,但由于服务器配置不同,可能需要进行适应。
通过daemon_memcached插件存储的数据
进入
VARCHAR,
TEXT或
BLOB列,并且必须转换为数字操作。您可以在应用程序端执行转换,或者使用CAST()查询中的
函数。
来自数据库背景,您可能习惯于具有多列的通用SQL表。通过memcached代码访问的表可能只有少数甚至是一列保存数据值。
您可能会调整执行单行查询,插入,更新或删除的应用程序的某些部分,以提高关键代码段的性能。两个
查询(读取)和
DML(写)操作可以通过执行时更快基本上
InnoDB 分布式缓存
接口。写入的性能改进通常大于读取的性能改进,因此您可能会专注于调整执行日志记录或在网站上记录交互式选择的代码。
以下各节将更详细地探讨这些要点。
在调整现有MySQL模式或应用程序以使用
插件时,
请考虑memcached应用程序的这些方面daemon_memcached:
memcached密钥不能包含空格或换行符,因为这些字符在ASCII协议中用作分隔符。如果您使用包含空格的查找值,在调用使用它们作为键来变换前或将它们散列到值没有空格
add(),set(),
get(),等等。尽管理论上这些字符在使用二进制协议的程序中的键中是允许的,但您应该限制键中使用的字符以确保与广泛的客户端兼容。
如果表中存在简短的数字
主键列InnoDB,则通过将整数转换为字符串值,将其用作memcached的唯一查找键。如果
memcached服务器用于多个应用程序或多个
InnoDB表,请考虑修改名称以确保它是唯一的。例如,在数字值前加上表名,或数据库名和表名。
该daemon_memcached插件支持插入和读取InnoDB
具有INTEGER定义为主键的映射表。
对于使用memcached查询或存储的数据,不能使用分区表。
的分布式缓存协议围绕经过数字值作为字符串。要将数值存储在基础InnoDB表中,要实现可用于SQL函数(如SUM()或)的计数器,
AVG()例如:
使用VARCHAR具有足够字符的列来保存最大预期编号的所有数字(以及适用于负号,小数点或两者的附加字符)。
在任何使用列值执行算术的查询中,使用该CAST()函数将字符串中的值转换为整数或其他数字类型。例如:
#按字母顺序的条目返回为零。 SELECT CAST(c2作为无符号整数)FROM demo_test; #因为可能有0的数值,所以不能取消它们的资格。 #测试字符串值来查找那些是整数的值,并且只对这些值进行平均。 SELECT AVG(cast(c2 as unsigned integer))FROM demo_test 在哪里c2'0'和'9999999999'之间; #视图让你隐藏查询的复杂性。结果已经被转换; #无需每次重复转换函数和WHERE子句。 CREATE VIEW数字AS SELECT c1 KEY,CAST(c2 AS UNSIGNED INTEGER)val FROM demo_test WHERE c2 BETWEEN'0'和'9999999999'; SELECT SUM(val)FROM numbers;
通过调用将结果集中的任何字母值转换为0 CAST()。使用AVG()取决于结果集中行数的函数时,应包含WHERE用于过滤非数字值的子句。
如果InnoDB用作键的列的值可能超过250个字节,则将该值散列为小于250个字节。
要在daemon_memcached插件中使用现有的表格,请在表格中
为其定义一个条目innodb_memcache.containers
。要将该表作为所有memcached请求的缺省
值,请default在该name
列中指定一个值
,然后重新启动MySQL服务器以使更改生效。如果对不同类别的memcached数据使用多个表格,请在innodb_memcache.containers表格中用
name您选择的值设置多个表项
,然后发出
memcached请求,格式为
get @@或
nameset @@
在应用程序中指定要用于后续memcached请求的表。
name
有关使用预定义test.demo_test表以外的
表的示例,请参见
示例14.13,“将自己的表与InnoDB memcached应用程序一起使用”。有关所需的表格布局,请参见
第14.20.7节“InnoDB memcached插件内部”。
要将多个InnoDB表列值与memcached键/值对一起使用,请
在表格value_columns
的innodb_memcache.containers条目字段中指定用逗号,分号,空格或管道字符分隔的列名称InnoDB。例如,指定col1,col2,col3或
col1|col2|col3在该
value_columns字段中。
在将字符串传递给memcached add或
set调用之前,使用管道字符作为分隔符将列值连接成单个字符串
。该字符串会自动解压到正确的列中。每个
get调用都会返回一个单独的字符串,其中包含也由管道字符分隔的列值。您可以使用适当的应用程序语言语法解压缩这些值。
例14.13在InnoDB memcached应用程序中使用自己的表
此示例显示如何将自己的表与memcached用于数据操作的示例Python应用程序一起使用。
该示例假定
daemon_memcached按照第14.20.3节“设置InnoDB memcached插件”中的描述安装插件。它还假定您的系统已配置为运行使用该python-memcache模块的Python脚本。
创建multicol存储国家信息的表格,包括人口,区域和驾驶员侧数据('R'右侧和
'L'左侧)。
MySQL的>USE test;MySQL的>CREATE TABLE `multicol` (`country` varchar(128) NOT NULL DEFAULT '',`population` varchar(10) DEFAULT NULL,`area_sq_km` varchar(9) DEFAULT NULL,`drive_side` varchar(1) DEFAULT NULL,`c3` int(11) DEFAULT NULL,`c4` bigint(20) unsigned DEFAULT NULL,`c5` int(11) DEFAULT NULL,PRIMARY KEY (`country`)) ENGINE=InnoDB DEFAULT CHARSET=latin1;
在innodb_memcache.containers表格中插入一条记录,
以便daemon_memcached插件可以访问multicol表格。
MySQL的>INSERT INTO innodb_memcache.containers(name,db_schema,db_table,key_columns,value_columns,flags,cas_column,expire_time_column,unique_idx_name_on_key)VALUES('bbb','test','multicol','country','population,area_sq_km,drive_side','c3','c4','c5','PRIMARY');MySQL的>COMMIT;
该表的innodb_memcache.containers
记录multicol指定了一个name值
'bbb',它是表标识符。
如果InnoDB为所有memcached应用程序使用单个表,则name可以将该值设置
default为避免使用
@@表示法来切换表。
该db_schema列设置为
test,这是multicol表所在的数据库的名称。
该db_table列设置为
multicol,这是名称
InnoDB表。
key_columns被设置为唯一
country列。该
country列被定义为multicol表定义中的主键。
InnoDB数据被划分为三个表格列(,和
)population,
而不是单个表格列来存放组合数据值。为了适应多个值列,在字段中指定了逗号分隔的列列表
。在字段中定义的列是存储或检索值时使用的列。
area_sq_kmdrive_sidevalue_columnsvalue_columns
对值flags,
expire_time以及
cas_column字段基于在所使用的值demo.test的示例表。这些字段在使用daemon_memcached插件的应用程序中通常不重要,
因为MySQL会保持数据同步,并且不需要担心数据过期或过时。
该unique_idx_name_on_key字段设置为PRIMARY,它引用表中唯一country列
上定义的主索引
multicol。
将示例Python应用程序复制到文件中。在此示例中,示例脚本被复制到名为的文件中
multicol.py。
示例Python应用程序将数据插入
multicol表中并检索所有键的数据,演示如何InnoDB通过daemon_memcached插件访问
表
。
导入sys,os
导入memcache
def connect_to_memcached():
memc = memcache.Client(['127.0.0.1:11211'],debug = 0);
打印“连接到memcached”。
返回memc
def banner(message):
打印
打印“=”* len(消息)
打印消息
打印“=”* len(消息)
country_data = [
( “加拿大”, “34820000”, “9984670”, “R”),
( “USA”, “314242000”, “9826675”, “R”),
( “爱尔兰”, “6399152”, “84421”, “L”),
( “英国”, “62262000”, “243610”, “L”),
( “墨西哥”, “113910608”, “1972550”, “R”),
( “丹麦”, “5543453”, “43094”, “R”),
( “挪威”, “5002942”, “385252”, “R”),
( “UAE”, “8264070”, “83600”, “R”),
( “印”, “1210193422”, “3287263”, “L”),
( “中国”, “1347350000”, “9640821”, “R”),
]
def switch_table(memc,table):
键=“@@”+表
打印“通过为''+ key +''发出GET来将默认表切换为'”+表格+“'”。
result = memc.get(key)
def insert_country_data(memc):
横幅(“通过memcached接口插入初始数据”)
对于country_data中的项目:
country = item [0]
人口=项目[1]
区域=项目[2]
drive_side = item [3]
键=国家
value =“|”.join([population,area,drive_side])
打印“Key =”+键
打印“值=”+值
如果memc.add(键值):
打印“添加了新的密钥,值对。”
其他:
打印“更新现有密钥的值”。
memc.set(键,值)
def query_country_data(memc):
横幅(“检索所有密钥(国家名称)的数据”)
对于country_data中的项目:
key = item [0]
result = memc.get(key)
打印“这是从数据库中为键”+ key +“检索的结果:”
打印结果
(m_population,m_area,m_drive_side)= result.split(“|”)
打印“解压后的人口值:”+ m_population
打印“解包区域值:”+ m_area
打印“解压后的驱动器侧值:”+ m_drive_side
如果__name__ =='__main__':
memc = connect_to_memcached()
switch_table(MEMC, “BBB”)
insert_country_data(MEMC)
query_country_data(MEMC)
sys.exit(0)
示例Python应用笔记:
由于数据操作是通过memcached接口执行的,因此不需要数据库授权来运行应用程序。唯一需要的信息是memcached守护程序侦听的本地系统上的端口号 。
为了确保应用程序使用该
multicol表,switch_table()调用该函数,该
函数使用表示法执行虚拟get或
set请求
@@。name请求中的
值是
该
字段中定义bbb的
multicol表标识符
innodb_memcache.containers.name。
一个更具描述性的name价值可能被用在现实世界的应用程序中。这个例子只是说明了一个表格标识符被指定,而不是get
@@...请求中的表格名称。
用于插入和查询数据的实用函数演示了如何将Python数据结构转换为管道分隔值,以便将数据发送给MySQL
add或set
请求,以及如何解开get请求返回的管道分隔值。只有在将单个memcached值映射到多个MySQL表列时才需要额外处理。
运行示例Python应用程序。
外壳> python multicol.py
如果成功,示例应用程序将返回此输出:
连接到memcached。 通过为'@@ bbb'发布GET来将默认表切换为'bbb'。 ============================================== 通过memcached接口插入初始数据 ============================================== 键=加拿大 价值= 34820000 | 9984670 | R 增加了新的键值对。 键=美国 值= 314242000 | 9826675 | R 增加了新的键值对。 键=爱尔兰 值= 6399152 | 84421 | L 增加了新的键值对。 关键=英国 值= 62262000 | 243610 | L 增加了新的键值对。 关键=墨西哥 值= 113910608 | 1972550 | R 增加了新的键值对。 关键=丹麦 值= 5543453 | 43094 | R 增加了新的键值对。 关键=挪威 值= 5002942 | 385252 | R 增加了新的键值对。 关键=阿联酋 值= 8264070 | 83600 | R 增加了新的键值对。 关键=印度 值= 1210193422 | 3287263 | L 增加了新的键值对。 关键=中国 值= 1347350000 | 9640821 | R 增加了新的键值对。 ============================================ 检索所有键(国名)的数据 ============================================ 以下是加拿大主要数据库的检索结果: 34820000 | 9984670 | R 未包装的人口值:34820000 未包装的面积值:9984670 未包装的驱动器侧值:R 以下是美国主要数据库的检索结果: 314242000 | 9826675 | R 未包装的人口值:314242000 未包装的面积值:9826675 未包装的驱动器侧值:R 以下是爱尔兰关键数据库的检索结果: 6399152 | 84421 | L 未包装的人口值:6399152 未包装的面积值:84421 未包装的驱动器侧值:L 以下是英国主要数据库的检索结果: 62262000 | 243610 | L 未包装的人口值:62262000 未包装的面积值:243610 未包装的驱动器侧值:L 以下是墨西哥关键数据库的检索结果: 113910608 | 1972550 | R 未包装的人口值:113910608 未包装的面积值:1972550 未包装的驱动器侧值:R 以下是丹麦主要数据库的检索结果: 5543453 | 43094 | R 未包装的人口值:5543453 未包装的面积值:43094 未包装的驱动器侧值:R 以下是挪威主要数据库的检索结果: 5002942 | 385252 | R 未包装的人口值:5002942 未包装的面积值:385252 未包装的驱动器侧值:R 以下是从数据库中检索的关键阿联酋的结果: 8264070 | 83600 | R 未包装的人口值:8264070 未包装的面积值:83600 未包装的驱动器侧值:R 以下是从印度主要数据库中检索的结果: 1210193422 | 3287263 | L 未包装的人口值:1210193422 未包装的面积值:3287263 未包装的驱动器侧值:L 这是从关键中国数据库检索的结果: 1347350000 | 9640821 | R 未包装的人口值:1347350000 未包装的面积值:9640821 未包装的驱动器侧值:R
查询innodb_memcache.containers
表格以查看您之前为multicol表格插入的记录
。第一条记录是demo_test在初始daemon_memcached插件安装期间创建的表
的示例条目。第二条记录是您为multicol表格插入的条目
。
MySQL的> SELECT * FROM innodb_memcache.containers\G
*************************** 1. row ******************** *******
名称:aaa
db_schema:测试
db_table:demo_test
key_columns:c1
value_columns:c2
标志:c3
cas_column:c4
expire_time_column:c5
unique_idx_name_on_key:PRIMARY
*************************** 2. row ******************** *******
名称:bbb
db_schema:测试
db_table:multicol
key_columns:国家
value_columns:人口,area_sq_km,drive_side
标志:c3
cas_column:c4
expire_time_column:c5
unique_idx_name_on_key:PRIMARY
查询multicol表格以查看示例Python应用程序插入的数据。这些数据可用于MySQL
查询,它演示了如何使用SQL或通过应用程序(使用适当的MySQL连接器或API)访问相同的数据
。
MySQL的> SELECT * FROM test.multicol;
+ --------- + ------------ + ------------ + ------------ + ------ + ------ + ------ +
| 国家| 人口| area_sq_km | drive_side | c3 | c4 | c5 |
+ --------- + ------------ + ------------ + ------------ + ------ + ------ + ------ +
| 加拿大| 34820000 | 9984670 | R | 0 | 11 | 0 |
| 中国| 1347350000 | 9640821 | R | 0 | 20 | 0 |
| 丹麦| 5543453 | 43094 | R | 0 | 16 | 0 |
| 印度| 1210193422 | 3287263 | L | 0 | 19 | 0 |
| 爱尔兰| 6399152 | 84421 | L | 0 | 13 | 0 |
| 墨西哥| 113910608 | 1972550 | R | 0 | 15 | 0 |
| 挪威| 5002942 | 385252 | R | 0 | 17 | 0 |
| 阿联酋| 8264070 | 83600 | R | 0 | 18 | 0 |
| 英国| 62262000 | 243610 | L | 0 | 14 | 0 |
| USA | 314242000 | 9826675 | R | 0 | 12 | 0 |
+ --------- + ------------ + ------------ + ------------ + ------ + ------ + ------ +
定义被视为数字的列的长度时,始终允许足够的大小以保留必要的数字,小数点,符号字符,前导零等。字符串列(如a)VARCHAR中的太长值
会通过删除某些可能产生无意义数字值的字符而被截断。
(可选)在InnoDB存储memcached数据的表
上运行报告类型查询
。
您可以通过SQL查询生成报告,跨任何列执行计算和测试,而不仅仅是
country关键列。(因为以下示例仅使用来自少数几个国家/地区的数据,所以这些数字仅用于说明目的。)以下查询返回人们在右侧驾驶的国家的平均人口数,以及名称以“ U “:
MySQL的>SELECT AVG(population) FROM multicol WHERE drive_side = 'R';+ ------------------- + | 平均(人口)| + ------------------- + | 261304724.7142857 | + ------------------- + MySQL的>SELECT SUM(area_sq_km) FROM multicol WHERE country LIKE 'U%';+ ----------------- + | sum(area_sq_km)| + ----------------- + | 10153885 | + ----------------- +
因为population和
area_sq_km列存储字符数据而不是强类型的数字数据,所以函数(比如AVG()和函数
SUM()首先将每个值转换为数字)。这种方法
不适用于诸如<或>比较基于字符的值等运算符
时9
> 1000,这不是从一个子句中预期的,例如ORDER BY population DESC。。对于最准确的类型处理,针对将数字列转换为适当类型的视图执行查询。这种技术可以让你发布简单SELECT
*查询数据库应用程序,同时确保投射,筛选和排序是正确的。下面的例子显示了一个可以按照人口从高到低的顺序查找前三个国家的视图,其结果反映了multicol表中的最新数据,并将人口和面积数字视为数字:
MySQL的>CREATE VIEW populous_countries ASSELECTcountry,cast(population as unsigned integer) population,cast(area_sq_km as unsigned integer) area_sq_km,drive_side FROM multicolORDER BY CAST(population as unsigned integer) DESCLIMIT 3;MySQL的>SELECT * FROM populous_countries;+ --------- + ------------ + ------------ + ------------ + | 国家| 人口| area_sq_km | drive_side | + --------- + ------------ + ------------ + ------------ + | 中国| 1347350000 | 9640821 | R | | 印度| 1210193422 | 3287263 | L | | USA | 314242000 | 9826675 | R | + --------- + ------------ + ------------ + ------------ + MySQL的>DESC populous_countries;+ ------------ + --------------------- + ------ + ------ + - -------- ------- + + | 字段| 类型| 空| Key | 默认| 额外| + ------------ + --------------------- + ------ + ------ + - -------- ------- + + | 国家| varchar(128)| NO | | | | | 人口| bigint(10)unsigned | 是| | NULL | | | area_sq_km | int(9)unsigned | 是| | NULL | | | drive_side | varchar(1)| 是| | NULL | | + ------------ + --------------------- + ------ + ------ + - -------- ------- + +
InnoDB
在调整现有的memcached
应用程序以使用daemon_memcached
插件时,
请考虑MySQL和表的这些方面:
如果有键值超过几个字节,它可能是更有效地使用数字自动增量列作为
主键的的
InnoDB表格,并创造了独特的
二次指数
在包含列memcached的
键值。这是因为InnoDB
如果主键值以排序顺序添加(因为它们具有自动增量值),则对于大规模插入最适合执行。主键值包含在二级索引中,如果主键是一个长字符串值,则会占用不必要的空间。
如果使用memcached存储多个不同类别的信息
,请考虑InnoDB为每种类型的数据设置一个单独的
表。在innodb_memcache.containers表中定义其他表标识符
,并使用该
标记来存储和检索不同表中的项目。通过物理划分不同类型的信息,可以调整每个表格的特征以获得最佳空间利用率,性能和可靠性。例如,您可能启用
压缩@@对于拥有博客帖子的表格,但对于包含缩略图图像的表格不适用。您可能比另一个表更频繁地备份一个表,因为它保存关键数据。您可以在经常用于使用SQL生成报表的表上创建附加的
二级索引。
table_id.key
最好配置一组稳定的表定义以供daemon_memcached插件使用,并永久保留这些表。innodb_memcache.containers下次innodb_memcache.containers查询表格时,表格的更改
会生效
。容器表中的条目在启动时处理,并且每当containers.name使用@@符号请求无法识别的表格标识符(由定义的表格
)时将被查询
。因此,只要使用关联的表标识符,新条目就可见,但对现有条目的更改需要服务器重新启动才能生效。
当您使用默认的innodb_only
缓存策略,调用add(),
set(),incr(),等能成功,但依旧会触发调试消息如
while expecting 'STORED', got unexpected response
'NOT_STORED。调试消息的发生是因为
缓存策略InnoDB导致新值和更新值直接发送到
表而不保存在内存缓存中innodb_only。
因为InnoDB与memcached结合使用
需要将所有数据写入磁盘,不管是立即还是稍后,原始性能预计会比使用memcached本身稍慢
。在使用
InnoDB memcached插件时,请注意memcached操作的调优目标,以实现比等效SQL操作更好的性能。
基准测试表明,使用memcached 接口的查询和 DML操作(插入,更新和删除)比传统SQL更快。DML操作通常会看到更大的改进。因此,考虑首先使用写密集型应用程序来使用 memcached接口。还要考虑优先使用缺乏可靠性的快速轻量级机制的写入密集型应用的适应性。
最适合简单GET请求的查询类型是子句中包含单个子句或一组AND条件
的查询类型
WHERE:
SQL: SELECT col FROM tbl WHERE key ='key_value'; memcached的: 获得key_value SQL: SELECT col FROM tbl WHERE col1 = val1和col2 = val2和col3 = val3; memcached的: #因为你必须知道这三个值来查找关键字, #将它们组合成一个唯一的字符串并将其用作关键字 #用于所有ADD,SET和GET操作。 key_value = val1 +“:”+ val2 +“:”+ val3 获得key_value SQL: SELECT'键存在!' 从tbl WHERE EXISTS(SELECT col1 FROM tbl WHERE KEY ='key_value')LIMIT 1; memcached的: #通过询问其值并检查调用是否成功来测试密钥的存在性, #忽略值本身。对于存在检查,你通常只存储一个 #短值,例如“1”。 获得key_value
为了获得最佳性能,请将该daemon_memcached插件部署到
配置为典型数据库服务器的机器上,其中大部分系统RAM 通过
配置选项专用于InnoDB
缓冲池innodb_buffer_pool_size。对于具有多吉字节缓冲池的系统,innodb_buffer_pool_instances
当大多数操作涉及已经缓存在内存中的数据时,请考虑提高最大吞吐量的值
。
InnoDB有许多设置可以让您在发生崩溃时选择高可靠性与高写入工作负载期间的I / O开销量之间的平衡。例如,考虑设置
innodb_doublewrite来
0和
innodb_flush_log_at_trx_commit
到2。使用不同的innodb_flush_method设置测量性能
。
innodb_support_xa已弃用,将在未来版本中删除。从MySQL 5.7.10开始,InnoDB对XA事务中的两阶段提交的支持始终处于启用状态,并且innodb_support_xa不再允许禁用
。
有关为表操作减少或调整I / O的其他方法,请参见 第8.5.8节“优化InnoDB磁盘I / O”。
的1为默认值
daemon_memcached_r_batch_size
,并
daemon_memcached_w_batch_size
适用于结果的最大的可靠性和存储或更新的数据的安全性。
根据应用程序的类型,您可以增加其中的一个或两个设置以减少频繁提交操作的开销
。在繁忙的系统上,您可能会增加
daemon_memcached_r_batch_size,因为知道通过SQL创建的数据更改可能不会立即对memcached显示(也就是说,直到
处理了N更多get操作)。处理必须可靠存储每个写入操作的数据时,请将其
daemon_memcached_w_batch_size
设置为1。处理大量仅用于统计分析的更新时增加设置,在N崩溃中丢失上次
更新是可接受的风险。
例如,设想一个系统,监控穿过繁忙桥梁的交通情况,每天记录大约100,000辆车的数据。如果应用程序统计不同类型的车辆来分析流量模式,改变
daemon_memcached_w_batch_size
从1以100减少99%提交操作的I / O开销。如果发生故障,最多可丢失100条记录,这可能是一个可接受的误差范围。相反,如果应用程序进行自动收费为每一辆汽车,您将设置
daemon_memcached_w_batch_size
以1确保每个收费记录被立即保存到磁盘。
由于在磁盘上InnoDB组织
memcached密钥值的方式,如果您有大量密钥要创建,可能会更快地按应用程序中的键值对数据项进行排序,并按
add排序顺序对其进行排序,而不是按任意顺序创建密钥。
的memslap命令,这是常规的一部分,分布式缓存分布,但不包含在daemon_memcached插件,可以进行基准测试的不同配置是有用的。它也可以用来生成样本键/值对以用于您自己的基准。有关
详细信息,请参阅
libmemcached命令行实用程序。
不同于传统的分布式缓存,该
daemon_memcached插件可以让你控制通过将呼叫产生的数据值的耐用性
add,set,
incr,等等。默认情况下,通过memcached接口写入的数据存储到磁盘,并调用get从磁盘返回最新值。尽管默认行为不能提供最佳的原始性能,但与InnoDB表格的SQL接口相比仍然很快。
在您获得使用daemon_memcached插件的经验时
,您可以考虑放宽非关键数据类的耐久性设置,在发生中断时可能丢失一些更新的值,或者返回稍微过时的数据。
耐久性和原始性能之间的一个折衷是新数据和更改数据的提交频率 。如果数据非常重要,应该立即执行,以便在发生崩溃或中断时安全。如果数据不那么重要,例如在崩溃后重置的计数器或记录您可能会丢失的数据,则可能需要较高的原始吞吐量,而提交的频率较低。
当memcached操作插入,更新或删除基础InnoDB
表中的数据时,可能会InnoDB立即(if daemon_memcached_w_batch_size=1)或稍后(如果该
daemon_memcached_w_batch_size
值大于1)将更改提交到
表中
。无论哪种情况,更改都无法回滚。如果增加值
daemon_memcached_w_batch_size
以避免繁忙时间内的I / O开销较高,则在工作负载减少时,提交可能会不频繁。作为一项安全措施,后台线程会定期自动提交通过memcached API 进行的更改。间隔由...控制
innodb_api_bk_commit_interval
配置选项,其默认设置为
5秒。
当memcached操作插入或更新基础InnoDB表中的数据时,更改后的数据对其他memcached请求立即可见,
因为新值仍保留在内存高速缓存中,即使它尚未在MySQL端提交。
当一个memcached操作(例如
get或incr在底层InnoDB
表上导致查询或DML操作)时,您可以控制操作是否会看到写入表中的最新数据,只有已提交的数据或事务隔离级别的其他变体
。使用innodb_api_trx_level
配置选项来控制此功能。为此选项指定的数值对应于隔离级别,例如
REPEATABLE READ。innodb_api_trx_level有关其他设置的信息,请参阅该选项的说明
。
严格的隔离级别可确保您检索的数据不会回滚或突然更改,从而导致后续查询返回不同的值。但是,严格的隔离级别要求更高的锁定 开销,这可能导致等待。对于不使用长时间运行的事务的NoSQL样式的应用程序,通常可以使用默认隔离级别或切换到不太严格的隔离级别。
innodb_api_disable_rowlock
当通过插件的memcached请求
daemon_memcached导致DML操作时,
该选项可用于禁用行锁定
。默认情况下,innodb_api_disable_rowlock设置为OFF这意味着
memcached请求行锁定
get和set操作。当innodb_api_disable_rowlock设置为
ON,memcached请求表锁,而不是行锁。
该innodb_api_disable_rowlock选项不是动态的。它必须在启动时在mysqld命令行中指定
或输入到MySQL配置文件中。
默认情况下,您可以执行DDL
操作,例如插件ALTER TABLE使用的表格daemon_memcached。为避免将这些表用于高吞吐量应用程序时可能发生的减速,请innodb_api_enable_mdl在启动时启用这些表以禁用DDL操作
。当通过memcached和SQL 访问相同的表时,此选项不太合适,因为它会阻止CREATE INDEX
表上的语句,这对于运行报表查询可能很重要。
该innodb_memcache.cache_policies表指定是否将通过memcached接口写入的数据存储
到磁盘(innodb_only默认值); 在内存中,与传统的memcached
(cache-only)一样; 或两者(caching)。
使用该caching设置,如果
memcached在内存中找不到密钥,它将在InnoDB表中搜索该值。如果值在
表中的磁盘上更新但尚未从内存高速缓存中过期,那么从get该caching设置下的调用
返回的值可能会过时InnoDB。
缓存策略可以独立设定
get,set(包括
incr和decr),
delete和flush
操作。
例如,您可能允许get和
set操作查询或更新表和memcached的(使用在同一时间内存缓存caching设置),同时使
delete,flush或(使用上都在内存中拷贝只能操作
cache_only设置)。这样,删除或刷新项目只会使缓存中的项目过期,并InnoDB
在下次请求项目时从表格返回最新值。
MySQL的>SELECT * FROM innodb_memcache.cache_policies;+ -------------- + ------------- ------------- + ------ + --------- + -------------- + | policy_name | get_policy | set_policy | delete_policy | flush_policy | + -------------- + ------------- ------------- + ------ + --------- + -------------- + | cache_policy | innodb_only | innodb_only | innodb_only | innodb_only | + -------------- + ------------- ------------- + ------ + --------- + -------------- + MySQL的>UPDATE innodb_memcache.cache_policies SET set_policy = 'caching'WHERE policy_name = 'cache_policy';
innodb_memcache.cache_policies值仅在启动时读取。更改此表中的值后,请卸载并重新安装daemon_memcached
插件以确保更改生效。
MySQL的>UNINSTALL PLUGIN daemon_memcached;MySQL的>INSTALL PLUGIN daemon_memcached soname "libmemcached.so";
基准测试表明,daemon_memcached
插件加速DML操作(插入,更新和删除)超过加速查询。因此,考虑集中在I / O绑定的写密集型应用程序上的初始开发工作,并寻找机会将MySQL与
daemon_memcached插件一起用于新的写密集型应用程序。
单行DML语句是转化为memcached操作的最简单的语句类型。
INSERT变add,
UPDATE变set,
incr还是decr和
DELETE成为delete。这些操作保证只在通过memcached接口发布时才影响一行,因为key它在表中是唯一的。
在以下SQL示例中,基于表中的配置t1引用用于memcached操作的
innodb_memcache.containers表。
key指的是下面列出的列
key_columns,并且val
是指列在下面的列
value_columns。
INSERT INTO t1(key,val)VALUES(some_key,some_value); SELECT val FROM t1 WHERE key =some_key; UPDATE t1 SET val =new_valueWHERE key =some_key; UPDATE t1 SET val = val + x WHERE key =some_key; DELETE FROM t1 WHERE key =some_key;
以下TRUNCATE TABLE和
DELETE从表中删除所有行的语句与flush_all操作相对应
,其中的
操作与上例中的t1配置为memcached操作的表
一样。
TRUNCATE TABLE t1; DELETE FROM t1;
您可以通过标准SQL接口访问基础InnoDB表(test.demo_test默认情况下)。但是,有一些限制:
在查询也通过memcached接口访问的表时
,请记住,
可以将memcached操作配置为定期提交,而不是在每次写入操作之后进行提交。该行为由daemon_memcached_w_batch_size
选项控制
。如果此选项设置为大于的值
1,请使用READ
UNCOMMITTED查询来查找刚刚插入的行。
MySQL的>SET SESSSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;MySQL的>SELECT * FROM demo_test;+ ------ + ------ + ------ + ------ + ----------- ------ + + - ---- + ------ + ------ + ------ + ------ + | cx | cy | c1 | cz | c2 | ca | CB | c3 | cu | c4 | C5 | + ------ + ------ + ------ + ------ + ----------- ------ + + - ---- + ------ + ------ + ------ + ------ + | NULL | NULL | a11 | NULL | 123456789 | NULL | NULL | 10 | NULL | 3 | NULL | + ------ + ------ + ------ + ------ + ----------- ------ + + - ---- + ------ + ------ + ------ + ------ +
当使用也通过memcached接口访问的SQL修改表时,可以配置memcached操作来定期启动新的事务,而不是每次读取操作。该行为由daemon_memcached_r_batch_size
选项控制
。如果此选项设置为大于此值
1,则使用SQL对表进行的更改不会立即对memcached
操作可见。
该InnoDB表是IS(意向共享)或IX(意向排除)锁定用于交易中的所有操作。如果增加daemon_memcached_r_batch_size
并且
daemon_memcached_w_batch_size
大大超出
其默认值
1,则表很可能会在每个操作之间锁定,从而阻止
表上的DDL语句。
由于该daemon_memcached插件支持MySQL 二进制日志,因此可以复制通过memcached接口在主服务器上进行的更新以进行备份,平衡密集读取工作负载和高可用性。二进制日志记录支持所有memcached命令。
您不需要daemon_memcached
在从属服务器上设置插件。这种配置的主要优点是增加了主设备上的写入吞吐量。复制机制的速度不受影响。
以下部分介绍如何在使用daemon_memcachedMySQL复制插件时使用二进制日志功能。假设您已经完成了第14.20.3节“设置InnoDB memcached插件”中描述的设置。
要将daemon_memcached插件与MySQL 二进制日志一起使用,请启用
主服务器innodb_api_enable_binlog
上的配置选项
。该选项只能在服务器启动时设置。您还必须使用该选项在主服务器上启用MySQL二进制日志
。您可以将这些选项添加到MySQL配置文件或
mysqld命令行中。
--log-bin
mysqld ... --log-bin --innodb_api_enable_binlog = 1
如第16.1.2节“设置基于二进制日志文件位置的复制”中所述配置主服务器和从服务器 。
使用mysqldump创建主数据快照,并将快照同步到从服务器。
主外壳>mysqldump --all-databases --lock-all-tables > dbdump.db从外壳>mysql < dbdump.db
在主服务器上,发出SHOW MASTER
STATUS获取主二进制日志坐标。
MySQL的> SHOW MASTER STATUS;
在从服务器上,使用CHANGE
MASTER TO语句来使用主二进制日志坐标设置从服务器。
MySQL的>CHANGE MASTER TOMASTER_HOST='localhost',MASTER_USER='root',MASTER_PASSWORD='',MASTER_PORT = 13000,MASTER_LOG_FILE='0.000001,MASTER_LOG_POS=114;
启动从站。
MySQL的> START SLAVE;
如果错误日志输出类似于以下内容的输出,则从设备已准备好进行复制。
2013-09-24T13:04:38.639684Z 49 [注] Slave I / O线程:连接到 主'root @ localhost:13000',复制开始日志'0.000001' 在位置114
本示例演示如何
使用memcached
和telnet 测试
InnoDB memcached复制配置以插入,更新和删除数据。MySQL客户端用于验证主服务器和从服务器上的结果。
该示例使用该demo_test表,该表由innodb_memcached_config.sql配置脚本在daemon_memcached插件的初始设置期间
创建
。该
demo_test表包含一个示例记录。
使用该set命令插入记录test1,其中的标志值为
10,过期值为
0,cas值为1,值为
t1。
telnet 127.0.0.1 11211尝试127.0.0.1 ... 连接到127.0.0.1。 转义字符是'^]'。set test1 10 0 1t1STORED
在主服务器上,检查记录是否已插入demo_test表中。假设
demo_test表格以前未被修改,应该有两个记录。带键的示例记录AA,以及刚刚插入的记录,其中的一个键test1。的
c1列映射到键时,
c2列的值,该
c3列的标志值,该
c4列的值CAS,和
c5列的到期时间。由于未使用,到期时间设置为0。
MySQL的> SELECT * FROM test.demo_test;
+ ------- + -------------- + ------ + ------ + ------ +
| c1 | c2 | c3 | c4 | c5 |
+ ------- + -------------- + ------ + ------ + ------ +
| AA | HELLO,HELLO | 8 | 0 | 0 |
| test1 | t1 | 10 | 1 | 0 |
+ ------- + -------------- + ------ + ------ + ------ +
检查以确认相同记录已复制到从属服务器。
MySQL的> SELECT * FROM test.demo_test;
+ ------- + -------------- + ------ + ------ + ------ +
| c1 | c2 | c3 | c4 | c5 |
+ ------- + -------------- + ------ + ------ + ------ +
| AA | HELLO,HELLO | 8 | 0 | 0 |
| test1 | t1 | 10 | 1 | 0 |
+ ------- + -------------- + ------ + ------ + ------ +
使用该set命令将密钥更新为值new。
telnet 127.0.0.1 11211尝试127.0.0.1 ... 连接到127.0.0.1。 转义字符是'^]'。set test1 10 0 2newSTORED
更新被复制到从服务器(注意cas值也被更新)。
MySQL的> SELECT * FROM test.demo_test;
+ ------- + -------------- + ------ + ------ + ------ +
| c1 | c2 | c3 | c4 | c5 |
+ ------- + -------------- + ------ + ------ + ------ +
| AA | HELLO,HELLO | 8 | 0 | 0 |
| test1 | 新的| 10 | 2 | 0 |
+ ------- + -------------- + ------ + ------ + ------ +
test1使用delete命令
删除记录
。
telnet 127.0.0.1 11211尝试127.0.0.1 ... 连接到127.0.0.1。 转义字符是'^]'。delete test1DELETED
当delete操作复制到从站时,从站上的test1记录也被删除。
MySQL的> SELECT * FROM test.demo_test;
+ ---- + -------------- + ------ + ------ + ------ +
| c1 | c2 | c3 | c4 | c5 |
+ ---- + -------------- + ------ + ------ + ------ +
| AA | HELLO,HELLO | 8 | 0 | 0 |
+ ---- + -------------- + ------ + ------ + ------ +
使用该flush_all命令从表中删除所有行
。
telnet 127.0.0.1 11211尝试127.0.0.1 ... 连接到127.0.0.1。 转义字符是'^]'。flush_all好
MySQL的> SELECT * FROM test.demo_test;
空集(0.00秒)
Telnet到主服务器并输入两条新记录。
telnet 127.0.0.1 11211尝试127.0.0.1 ... 连接到127.0.0.1。 转义字符是'^]'set test2 10 0 4againSTOREDset test3 10 0 5again1STORED
确认两条记录已复制到从属服务器。
MySQL的> SELECT * FROM test.demo_test;
+ ------- + -------------- + ------ + ------ + ------ +
| c1 | c2 | c3 | c4 | c5 |
+ ------- + -------------- + ------ + ------ + ------ +
| test2 | 再次| 10 | 4 | 0 |
| test3 | again1 | 10 | 5 | 0 |
+ ------- + -------------- + ------ + ------ + ------ +
使用该flush_all命令从表中删除所有行
。
telnet 127.0.0.1 11211尝试127.0.0.1 ... 连接到127.0.0.1。 转义字符是'^]'。flush_all好
检查以确保该flush_all
操作已在副服务器上复制。
MySQL的> SELECT * FROM test.demo_test;
空集(0.00秒)
二进制日志格式:
大多数memcached操作都映射到
DML语句(类似于插入,删除,更新)。由于MySQL服务器没有处理实际的SQL语句,因此所有的
memcached命令(除了
flush_all)都使用基于行的复制(RBR)日志记录,这与任何服务器binlog_format设置无关
。
的分布式缓存
flush_all命令被映射到
TRUNCATE TABLE命令。由于
DDL命令只能使用基于语句的日志记录,因此flush_all
通过发送TRUNCATE TABLE语句来复制该命令
。
交易方式:
事务
的概念
通常不是memcached
应用程序的一部分。出于性能考虑,
daemon_memcached_r_batch_size
并且
daemon_memcached_w_batch_size
用于控制读取和写入事务的批量大小。这些设置不会影响复制。InnoDB
成功完成后,基础表上的每个SQL操作都将被复制。
daemon_memcached_w_batch_size
is
的默认值
是1,这意味着每个
memcached写入操作立即提交。此默认设置会产生一定的性能开销,以避免主服务器和从服务器上可见数据的不一致。复制的记录始终可以立即在从服务器上使用。如果设置
daemon_memcached_w_batch_size
的值大于1,则通过memcached插入或更新的记录不会立即在主服务器上可见; 要在提交之前在主服务器上查看记录,请发出SET
TRANSACTION ISOLATION LEVEL READ UNCOMMITTED。
在InnoDB 分布式缓存
引擎访问InnoDB过
InnoDB的API,其中大部分是直接从嵌入式采纳InnoDB。
InnoDBAPI函数作为回调函数传递给
InnoDB memcached引擎。InnoDBAPI函数InnoDB直接访问表,大多数DML操作除外
TRUNCATE TABLE。
memcached命令是通过InnoDB memcached API实现的。下表概述了 memcached
命令如何映射到DML或DDL操作。
表14.16 memcached命令和相关的DML或DDL操作
| memcached命令 | DML或DDL操作 |
|---|---|
get |
读/取命令 |
set |
搜索后跟一个INSERT或
UPDATE(取决于是否存在密钥) |
add |
搜索后跟一个INSERTor
UPDATE |
replace |
搜索后跟一个 UPDATE |
append |
搜索后跟一个UPDATE(将数据附加到结果之前UPDATE) |
prepend |
一个搜索后跟一个UPDATE(在数据之前加上数据UPDATE) |
incr |
搜索后跟一个 UPDATE |
decr |
搜索后跟一个 UPDATE |
delete |
搜索后跟一个 DELETE |
flush_all |
TRUNCATE TABLE (DDL) |
本节介绍daemon_memcached插件使用的配置表
。该
cache_policies表,
config_options表,
containers表是由创建
innodb_memcached_config.sql的配置脚本innodb_memcache数据库。
MySQL的>USE innodb_memcache;数据库改变 MySQL的>SHOW TABLES;+ --------------------------- + | Tables_in_innodb_memcache | + --------------------------- + | cache_policies | | config_options | | 容器| + --------------------------- +
该cache_policies表定义了InnoDB
memcached安装的缓存策略。您可以指定单个策略get,
set,delete,和
flush单一高速缓存策略中的操作。所有操作的默认设置是
innodb_only。
innodb_only:
InnoDB用作数据存储。
cache-only:使用
memcached引擎作为数据存储。
caching:使用两者
InnoDB和
memcached引擎作为数据存储。在这种情况下,如果memcached在内存中找不到密钥,它将在InnoDB表中搜索该值
。
disable:禁用缓存。
表14.17 cache_policies列
| 柱 | 描述 |
|---|---|
policy_name |
缓存策略的名称。默认缓存策略名称是
cache_policy。 |
get_policy |
获取操作的缓存策略。有效值是
innodb_only,
cache-only,caching,或disabled。默认设置是
innodb_only。 |
set_policy |
设置操作的缓存策略。有效值是
innodb_only,
cache-only,caching,或disabled。默认设置是
innodb_only。 |
delete_policy |
用于删除操作的缓存策略。有效值是
innodb_only,
cache-only,caching,或disabled。默认设置是
innodb_only。 |
flush_policy |
刷新操作的缓存策略。有效值是
innodb_only,
cache-only,caching,或disabled。默认设置是
innodb_only。 |
该config_options表存储
可以在运行时使用SQL更改的与memcached相关的设置。支持的配置选项是separator和
table_map_delimiter。
表14.18 config_options列
| 柱 | 描述 |
|---|---|
Name |
memcached相关配置选项的名称。该config_options表支持以下配置选项
:
|
Value |
分配给memcached相关配置选项的值。 |
该containers表是三个配置表中最重要的一个。每个InnoDB
用于存储memcached值的containers表都必须在表中包含一个条目。该条目提供了InnoDB
表格列和容器表格列之间的映射,这是memcached使用
InnoDB表格所必需的
。
该containers表包含test.demo_test由innodb_memcached_config.sql
配置脚本创建的表的默认条目。要将
daemon_memcached插件与您自己的
InnoDB表一起使用,您必须在containers表中创建一个条目
。
表14.19容器列
| 柱 | 描述 |
|---|---|
name |
给容器的名称。如果InnoDB没有使用@@
表示法按名称请求表,则daemon_memcached插件将使用值为
的InnoDB表
。如果没有这样的条目,则表中的第一个条目按字母顺序排列
(升序),从而确定默认
表。containers.namedefaultcontainersnameInnoDB |
db_schema |
InnoDB表所在的数据库的名称。这是一个必需的值。 |
db_table |
InnoDB存储memcached值的表
的名称。这是一个必需的值。 |
key_columns |
InnoDB表中包含memcached操作的查找键值的列。这是一个必需的值。 |
value_columns |
InnoDB存储memcached数据的表列(一个或多个)
。可以使用表中指定的分隔符指定多列
innodb_memcached.config_options。默认情况下,分隔符是管道字符(“ | ”)。要指定多个列,请使用定义的分隔符分隔它们。例如:
col1|col2|col3。这是一个必需的值。 |
flags |
InnoDB用作memcached的标志(用户定义的数值,与主值一起存储和检索)的表列
。如果memcached值映射到多个列,则标志值可用作某些操作(如incr,prepend)
的列说明符
,以便在指定列上执行操作。例如,如果您已将映射
到三个
表列,并且只希望在一列上执行增量操作,请使用
列来指定列。如果你不使用value_columnsInnoDBflagsflags列,设置一个值0来表示它未被使用。 |
cas_column |
InnoDB存储比较和交换(cas)值的表列。该cas_column值与memcached散列对不同服务器的请求以及缓存内存中数据的方式有关。由于InnoDB
memcached插件与单个memcached守护进程紧密集成,并且内存中缓存机制由MySQL和
InnoDB缓冲池处理,因此很少需要此列。如果您不使用此列,请将值设置0为表示未使用。 |
expire_time_column |
InnoDB存储到期值的表列。该expire_time_column值与memcached散列对不同服务器的请求以及缓存内存中数据的方式有关。由于InnoDB
memcached插件与单个memcached守护进程紧密集成,并且内存中缓存机制由MySQL和
InnoDB缓冲池处理,因此很少需要此列。如果您不使用此列,请设置值0以指示该列未使用。最长过期时间定义为INT_MAX32 或2147483647秒(约68年)。 |
unique_idx_name_on_key |
键列上索引的名称。它必须是一个独特的索引。它可以是主键或
辅助索引。最好使用InnoDB表格的主键
。使用主键可避免使用辅助索引时执行的查找。您无法
为memcached查找制作
覆盖索引 ;
如果您尝试通过键和值列定义复合二级索引,则会返回错误。InnoDB |
你必须提供一个值db_schema,
db_name,key_columns,
value_columns和
unique_idx_name_on_key。指定
0的flags,
cas_column以及
expire_time_column如果它们是未使用。如果不这样做可能会导致您的设置失败。
key_columns:memcached密钥的最大限制
是250个字符,这由memcached执行。映射的键必须是非空CHAR或
VARCHAR类型。
cas_column:该cas
值是一个64位整数。它必须映射到
BIGINT至少8个字节。如果您不使用此列,请将值设置
0为表示未使用。
expiration_time_column:必须映射到
INTEGER至少4个字节。到期时间定义为Unix时间的32位整数(1970年1月1日以来的秒数,32位值)或从当前时间开始的秒数。对于后者,秒数不得超过60 * 60 * 24 * 30(30天内的秒数)。如果客户端发送的号码较大,服务器认为它是一个真正的Unix时间值,而不是与当前时间的偏移量。如果您不使用此列,请将值设置
0为表示未使用。
flags:必须映射到
INTEGER至少32位,并且可以为NULL。如果您不使用此列,请将值设置0为表示未使用。
在插件加载时执行预检查以强制实施列约束。如果发现不匹配,则插件未加载。
在插件初始化期间,当InnoDB
memcached配置了containers表中定义的信息时,将containers.value_columns根据映射InnoDB表验证定义的每个映射列
。如果InnoDB映射多个表列,则会进行检查以确保每列均存在并且是正确的类型。
在运行时,对于memcached插入操作,如果分隔值的数量多于映射列的数量,则仅采用映射值的数量。例如,如果有6个映射列,并且提供了7个定界值,则只会采用前6个定界值。第七个分隔值被忽略。
如果分隔值少于映射列,则未填充列设置为NULL。如果未填充的列不能设置为NULL,则插入操作将失败。
如果一个表的列数多于映射值,则额外的列不会影响结果。
该innodb_memcached_config.sql
配置脚本创建一个demo_test
表中的test数据库,它可以用来验证InnoDB memcached的
设置完成后立即安装插件。
该innodb_memcached_config.sql
配置脚本还创建了一个条目
demo_test表中的
innodb_memcache.containers表。
MySQL的>SELECT * FROM innodb_memcache.containers\G*************************** 1. row ******************** ******* 名称:aaa db_schema:测试 db_table:demo_test key_columns:c1 value_columns:c2 标志:c3 cas_column:c4 expire_time_column:c5 unique_idx_name_on_key:PRIMARY MySQL的>SELECT * FROM test.demo_test;+ ---- + ------------------ + ------ + ------ + ------ + | c1 | c2 | c3 | c4 | c5 | + ---- + ------------------ + ------ + ------ + ------ + | AA | HELLO,HELLO | 8 | 0 | 0 | + ---- + ------------------ + ------ + ------ + ------ +
本节介绍使用InnoDB memcached插件时可能遇到的问题。
如果在MySQL错误日志中遇到以下错误,服务器可能无法启动:
未能为打开的文件设置rlimit。尝试以root身份运行或请求较小的maxconns值。
错误消息来自memcached 守护进程。一种解决方法是提高操作系统对打开文件数量的限制。用于检查和增加打开文件限制的命令因操作系统而异。这个例子显示了Linux和OS X的命令:
#Linux 外壳>ulimit -n1024 shell>ulimit -n 4096shell>ulimit -n4096 #OS X 外壳>ulimit -n256 shell>ulimit -n 4096shell>ulimit -n4096
另一种解决方案是减少memcached
守护进程允许的并发连接数。为此,请
在MySQL配置文件的配置参数中对-c
memcached选项
进行编码daemon_memcached_option。该
-c选项的默认值为1024。
的[mysqld] ... loose-daemon_memcached_option =' - c 64'
要解决
memcached守护程序无法存储或检索InnoDB表数据的问题,请
在MySQL配置文件的配置参数中对-vvv memcached选项进行编码
daemon_memcached_option。检查MySQL错误日志以获取与memcached相关的调试输出
操作。
的[mysqld] ... 松daemon_memcached_option = ' - VVV'
如果指定保存memcached 值的列是错误的数据类型(如数字类型而不是字符串类型),则尝试存储键/值对将失败,并且不会显示特定的错误代码或消息。
如果该daemon_memcached插件导致MySQL服务器启动问题,则可以daemon_memcached在解决问题时通过在该项下添加此行来临时禁用该
插件
[mysqld]在MySQL配置文件中组:
daemon_memcached = OFF
例如,如果您INSTALL
PLUGIN在运行innodb_memcached_config.sql配置脚本来设置必要的数据库和表之前运行语句
,则服务器可能会崩溃并且无法启动。如果您错误地配置了一个条目,服务器也可能无法启动
innodb_memcache.containers表中。
卸载memcached MySQL实例插件,请发出以下语句:
MySQL的> UNINSTALL PLUGIN daemon_memcached;
如果daemon_memcached在每个实例中启用了插件的同一台计算机上运行MySQL的多个实例,请使用
daemon_memcached_option
配置参数为每个插件指定唯一的
memcached端口
daemon_memcached。
如果SQL语句找不到InnoDB
表或在表中找不到数据,但
memcached API调用检索预期的数据,则InnoDB表中可能缺少表
的条目
innodb_memcache.containers,或者您可能没有InnoDB
通过发布来切换到正确的表a get或
set使用
符号的请求
。更改了的现有条目,也会发生此问题
@@table_idinnodb_memcache.containers而不重新启动MySQL服务器,。自由格式的存储机制非常灵活,可以让您存储或检索多列值的请求,例如
col1|col2|col3即使守护进程正在使用test.demo_test将值存储在单个列中的表,也可能仍然有效。
在定义您自己的InnoDB用于daemon_memcached插件的表并将表中的列定义为时NOT
NULL,请确保NOT NULL在将表的记录插入表中时为列
提供值
innodb_memcache.containers。如果记录的
INSERT语句
innodb_memcache.containers包含的分隔值少于映射列的分隔值,则将未填充的列设置为NULL。尝试将NULL值插入NOT
NULL列会导致
INSERT失败,这可能只有在重新初始化daemon_memcached插件以将更改应用到innodb_memcache.containers表后才会变得明显
。
如果cas_column与
expire_time_column该字段
innodb_memcached.containers的表被设置为NULL,尝试加载时,返回以下错误的memcached
插件:
InnoDB_Memcached:配置表'containers'中的第6列 数据库'innodb_memcache'具有无效的NULL值。
该memcached的插件拒绝的使用
NULL在cas_column
与expire_time_column列。将这些列的值设置为0列未使用时的值。
随着memcached密钥和值的长度增加,您可能会遇到大小和长度限制。
当密钥超过250个字节时, memcached操作返回错误。目前这是memcached中的一个固定限制 。
InnoDB如果值超过768字节,3072字节或innodb_page_size值的一半,则可能会遇到表限制
。如果您打算在值列上创建索引以使用SQL在该列上运行报表生成查询,则这些限制主要适用。有关详细信息,请参见
第14.8.1.7节“InnoDB表限制”。
键值组合的最大大小为1 MB。
如果您在不同版本的MySQL服务器之间共享配置文件,那么使用该daemon_memcached插件的最新配置选项可能会导致旧版本MySQL的启动错误。为避免兼容性问题,请使用loose带选项名称的前缀。例如,使用
loose-daemon_memcached_option='-c 64'
而不是daemon_memcached_option='-c 64'。
没有限制或检查来验证字符集设置。memcached以字节为单位存储和检索键和值,因此不是字符集敏感的。但是,您必须确保 memcached客户端和MySQL表使用相同的字符集。
memcached连接被阻止访问包含索引虚拟列的表。访问索引虚拟列需要回调服务器,但 memcached连接无法访问服务器代码。
以下一般准则适用于故障排除
InnoDB问题:
当一个操作失败或者您怀疑有bug时,请查看MySQL服务器错误日志(参见第5.4.2节“错误日志”)。
第B.3节“服务器错误代码和消息”提供InnoDB了您可能遇到的一些常见特定错误的疑难解答信息
。
如果失败与
死锁有关,请innodb_print_all_deadlocks
启用该
选项,以便将有关每个死锁的详细信息打印到MySQL服务器错误日志中。有关死锁的信息,请参见第14.5.5节“InnoDB中的死锁”。
与InnoDB数据字典相关的问题包括失败的CREATE TABLE
语句(孤立表文件),无法打开
InnoDB文件以及系统找不到指定错误的路径。有关这些问题和错误的信息,请参见
第14.21.3节“InnoDB数据字典操作故障排除”。
在进行故障排除时,通常最好从命令提示符运行MySQL服务器,而不是通过
mysqld_safe或Windows服务运行。然后,您可以看到mysqld向控制台输出的内容,从而更好地掌握正在发生的事情。在Windows上,启动mysqld并使用
--console选项将输出定向到控制台窗口。
启用InnoDB监视器以获取有关问题的信息(请参见
第14.17节“InnoDB监视器”)。如果问题与性能相关,或者您的服务器似乎挂起,则应启用标准的Monitor以打印有关内部状态的信息InnoDB。如果问题出在锁上,请启用锁定监视器。如果问题出现在表创建,表空间或数据字典操作中,请参阅
InnoDB信息模式系统表以检查InnoDB内部数据字典的内容。
InnoDBInnoDB在以下情况下暂时启用标准
监视器输出:
一个很长的信号量等待
InnoDB 无法在缓冲池中找到空闲块
超过67%的缓冲池被锁堆或自适应散列索引占用
如果您怀疑某个表已损坏,请CHECK TABLE在该表上运行
。
InnoDBI / O问题
的故障排除步骤取决于发生问题的时间:在MySQL服务器启动期间,或者由于文件系统级别的问题导致DML或DDL语句失败的正常操作期间。
如果InnoDB尝试初始化表空间或其日志文件时出现问题,请删除由InnoDB所有
ibdata文件和所有ib_logfile文件创建的所有
文件。如果您已经创建了一些
InnoDB表,那么也可以从MySQL数据库目录中删除.frm这些表的相应
文件以及任何
.ibd文件(如果您使用多个表空间)。然后InnoDB再次尝试
数据库创建。为了最简单的故障排除,请从命令提示符处启动MySQL服务器,以便查看发生了什么。
如果InnoDB在文件操作过程中打印操作系统错误,通常该问题有以下解决方案之一:
确保InnoDB数据文件目录和InnoDB日志目录存在。
确保mysqld具有在这些目录中创建文件的访问权限。
确保mysqld可以读取正确的
my.cnf或my.ini
选项文件,以便它以您指定的选项开始。
确保磁盘未满并且您没有超出任何磁盘配额。
确保您为子目录和数据文件指定的名称不会发生冲突。
再次检查innodb_data_home_dir和
innodb_data_file_path值的语法
。特别是,MAX该innodb_data_file_path选项中的任何值
都是硬性限制,超过该限制会导致严重错误。
要调查数据库页面损坏情况,可以使用数据库转储表格
SELECT ... INTO
OUTFILE。通常,以这种方式获得的大部分数据是完整的。严重的损坏可能会导致语句或
后台操作崩溃或断言,甚至导致前滚恢复崩溃。在这种情况下,您可以使用该
选项强制存储引擎启动,同时防止后台操作运行,以便转储表。例如,可以在重新启动服务器之前将以下行添加到选项文件的部分:
SELECT * FROM
tbl_nameInnoDBInnoDBinnodb_force_recoveryInnoDB[mysqld]
的[mysqld] innodb_force_recovery = 1
innodb_force_recovery
在紧急情况下,
只能设置为大于0的值,以便您可以启动InnoDB并转储您的表格。在此之前,请确保您有数据库的备份副本,以备需要重新创建时使用。4或更大的值可能会永久损坏数据文件。innodb_force_recovery在成功测试数据库的单独物理副本上的设置后,只能在生产服务器实例上使用
4或更大的设置。强制InnoDB恢复时,应始终
innodb_force_recovery=1按照需要逐步增加值。
innodb_force_recovery默认情况下为0(没有强制恢复的正常启动)。允许的非零值
innodb_force_recovery 1到6.较大的值包括较小值的功能。例如,值3包括值1和2的所有功能。
如果您可以将表格转储innodb_force_recovery为3或更少的
值,那么相对安全的是只有损坏的单个页面上的一些数据丢失。值4或更大被认为是危险的,因为数据文件可能永久损坏。由于数据库页面处于过时状态,因此值6被认为是非常激烈的,这反过来可能会在B树
和其他数据库结构中引入更多的损坏。
作为安全措施,在大于0 时InnoDB防止
INSERT,
UPDATE或
DELETE操作
innodb_force_recovery。innodb_force_recovery
设置为4或更大的位置InnoDB处于只读模式。
1
(SRV_FORCE_IGNORE_CORRUPT)
即使它检测到损坏的页面,也让服务器运行
。试图
跳过损坏的索引记录和页面,这有助于转储表格。
SELECT * FROM
tbl_name
2
(SRV_FORCE_NO_BACKGROUND)
3
(SRV_FORCE_NO_TRX_UNDO)
4
(SRV_FORCE_NO_IBUF_MERGE)
防止插入缓冲区合并操作。如果他们会导致崩溃,不会这样做。不计算表格
统计信息。该值可能会永久损坏数据文件。使用此值后,准备放弃并重新创建所有二级索引。设置
InnoDB为只读。
5
(SRV_FORCE_NO_UNDO_LOG_SCAN)
启动数据库时
不会查看撤消日志:
InnoDB即使未完成的事务也被视为已提交。该值可能会永久损坏数据文件。设置InnoDB为只读。
6
(SRV_FORCE_NO_LOG_REDO)
不会执行与恢复有关的重做日志前
滚。该值可能会永久损坏数据文件。使数据库页面处于过时状态,这反过来可能将更多的损坏引入B树和其他数据库结构。设置
InnoDB为只读。
你可以SELECT从表中转储它们。如果
innodb_force_recovery值为3或更少,则可以使用表格DROP或
CREATE表格。DROP
TABLE也支持innodb_force_recovery大于3 的
值,直到MySQL 5.7.17。从MySQL 5.7.18开始,
DROP TABLE不允许使用
innodb_force_recovery大于4值。
如果您知道给定的表在回滚时导致崩溃,则可以将其删除。如果遇到失败的批量导入导致的失控回滚ALTER TABLE,您可以终止mysqld进程,并设置
innodb_force_recovery为
3在没有回滚的情况下启动数据库,然后DROP设置导致失控回滚的表。
如果表数据中的腐败使您无法转储整个表内容,则使用 ORDER BY
子句可能能够在损坏的部分之后转储表的部分。
primary_key DESC
如果一个高innodb_force_recovery
值是必需的开始InnoDB,有可能是,可能导致(含有查询的复杂查询损坏的数据结构WHERE,ORDER
BY或其它条款)失败。在这种情况下,您可能只能运行基本SELECT * FROM t
查询。
有关表定义的信息既存储在.frm文件中,也存储
在InnoDB
数据字典中。如果您移动.frm文件,或者如果服务器在数据字典操作过程中崩溃,这些信息源可能会变得不一致。
如果数据字典损坏或一致性问题阻止您启动InnoDB,请参见
第14.21.2节“强制InnoDB恢复”以获取有关手动恢复的信息。
不同步数据字典的一个症状是
CREATE TABLE语句失败。如果发生这种情况,请查看服务器的错误日志。如果日志说该表已经存在于
InnoDB内部数据字典中,那么在InnoDB表空间文件中有一个没有相应.frm文件的孤立表。错误消息如下所示:
InnoDB:错误:InnoDB内部已经存在table test / parent InnoDB:数据字典。您是否删除了.frm文件 InnoDB:并没有使用DROP TABLE?你用过DROP DATABASE吗? InnoDB:用于MySQL版本<= 3.23.43的InnoDB表? InnoDB:参见InnoDB手册的限制部分。 InnoDB:您可以通过删除InnoDB中的孤立表 InnoDB:在另一个中创建具有相同名称的InnoDB表 InnoDB:数据库并将.frm文件移动到当前数据库。 InnoDB:然后MySQL认为表存在,并且DROP TABLE将会 InnoDB:成功。
您可以按照错误消息中给出的说明删除孤立表。如果您仍然无法DROP TABLE成功使用
,则问题可能是由于mysql客户端中的名称完成
。要解决此问题,请使用该
选项启动mysql客户端,
--skip-auto-rehash然后重试DROP TABLE。(当名称完成时,mysql会尝试构造一个表名列表,当刚刚描述的问题存在时,它将失败。)
随着innodb_file_per_table
启用(默认值),下面的消息可能会在启动时出现,如果一个
文件的每个表的
表空间文件(.ibd文件)是丢失:
[错误] InnoDB:文件操作中的操作系统错误编号2。 [错误] InnoDB:错误意味着系统找不到指定的路径。 [错误] InnoDB:无法打开数据文件为只读:'./test/t1.ibd'操作系统错误:71 [警告] InnoDB:忽略表空间`test / t1`,因为它无法打开。
要解决这些消息,请发出DROP
TABLE语句以从数据字典中删除有关缺少表的数据。
不同步数据字典的另一个症状是MySQL打印出一个无法打开InnoDB文件的错误
:
错误1016:无法打开文件:'child2.ibd'。(错误:1)
在错误日志中你可以找到这样的消息:
InnoDB:从内部数据字典中找不到表test / child2 InnoDB:虽然InnoDB的.frm文件存在。可能是你 InnoDB:已经删除并重新创建了InnoDB数据文件,但已经忘记了 InnoDB:删除InnoDB表的相应.frm文件?
这意味着有一个.frm
没有相应表格的孤儿文件
InnoDB。您可以.frm通过手动删除孤立
文件来删除它。
如果MySQL在就地ALTER TABLE操作过程中退出
(ALGORITHM=INPLACE),则可能会留下一个孤立的中间表,以占用系统空间。此外,在其他空白的常规表空间中的孤立中间表
可以防止您丢弃常规的表空间。本节介绍如何识别和删除孤儿中间表。
中间表名称以#sql-ib前缀(例如,
#sql-ib87-856498050)开头
。附带的
.frm文件有一个
#sql-*前缀,名称不同(例如#sql-36ab_2.frm)。
要识别系统上的孤立中间表,您可以查询
INFORMATION_SCHEMA.INNODB_SYS_TABLES。寻找开头的表名#sql。如果原始表驻留在每个
文件表的表
空间中,#sql-*.ibd则孤立中间表的表空间文件(
文件)应该在数据库目录中可见。
SELECT * FROM INFORMATION_SCHEMA.INNODB_SYS_TABLES WHERE NAME LIKE'%#sql%';
要删除孤立中间表,请执行以下步骤:
在数据库目录中,重命名该
#sql-*.frm文件以匹配孤立中间表的基本名称:
外壳> mv #sql-36ab_2.frm #sql-ib87-856498050.frm
如果没有.frm文件,可以重新创建它。该.frm文件必须与孤立中间表具有相同的表模式(它必须具有相同的列和索引),并且必须放置在孤立中间表的数据库目录中。
通过发出一条DROP TABLE语句来
删除孤立中间表,
#mysql50#在表名前加上表名,并用反引号括起表名。例如:
MySQL的> DROP TABLE `#mysql50##sql-ib87-856498050`;
该#mysql50#前缀告诉MySQL忽略file name safe encoding在MySQL 5.1中引入的。在反引号中包含表名是在具有特殊字符(例如“ # ”)的表名上执行SQL语句所必需的。
如果在ALTER TABLE将表移动到其他表空间的就地操作期间发生崩溃
,恢复过程会将该表恢复到其原始位置,但在目标表空间中保留孤立中间表。
如果MySQL在表复制ALTER TABLE操作(ALGORITHM=COPY)的中间退出
,那么您可能会留下一个孤立的临时表,这会占用系统空间。另外,在其他空的常规表空间中的孤立临时表
可以防止您丢弃常规表空间。本节介绍如何识别和删除孤立的临时表。
孤儿临时表名称以#sql-前缀(例如,
#sql-540_3)开头
。随附的
.frm文件与孤立临时表具有相同的基本名称。
如果没有.frm文件,可以重新创建它。该.frm文件必须与孤立临时表具有相同的表架构(它必须具有相同的列和索引),并且必须放置在孤立临时表的数据库目录中。
要识别系统上的孤立临时表,您可以查询
INFORMATION_SCHEMA.INNODB_SYS_TABLES。寻找开头的表名#sql。如果原始表驻留在每个
文件表的表
空间中,#sql-*.ibd则孤立临时表的表空间文件(
文件)应该在数据库目录中可见。
SELECT * FROM INFORMATION_SCHEMA.INNODB_SYS_TABLES WHERE NAME LIKE'%#sql%';
要删除一个孤立的临时表,通过发出一条DROP TABLE语句来删除这个表,在表
名的前面添加一个表,#mysql50#并用反引号括起表名。例如:
MySQL的> DROP TABLE `#mysql50##sql-540_3`;
该#mysql50#前缀告诉MySQL忽略
file name safe encoding在MySQL 5.1中引入的。在反引号中包含表名是在具有特殊字符(例如“ # ”)的表名上执行SQL语句所必需的。
与innodb_file_per_table
启用,如果可能会出现以下消息
.frm或.ibd文件(或两者)丢失:
InnoDB:在InnoDB数据字典中有表空间id N,
InnoDB:但是具有该id或名称的表空间不存在。有
InnoDB:你删除或移动了.ibd文件?
InnoDB:这也可能是使用CREATE TEMPORARY TABLE创建的表
InnoDB:其中的.ibd和.frm文件会自动删除MySQL,但是
InnoDB:表仍然存在于InnoDB内部数据字典中。
如果发生这种情况,请尝试以下过程来解决问题:
.frm在其他数据库目录中
创建一个匹配文件,并将其复制到孤立表所在的数据库目录。
发布DROP TABLE原始表格。这应该成功删除该表,并
InnoDB应该向错误日志中显示.ibd文件丢失的警告。
本过程介绍了如何将每个文件独立文件
还原
.ibd到另一个MySQL实例。如果系统表空间丢失或不可恢复,并且您想要.idb
在新的MySQL实例上恢复文件备份,则可以使用此过程。
该过程不支持
常规表空间 .ibd文件。
该过程假定您只有
.ibd文件备份,您正在恢复到最初创建孤立.idb文件的相同版本的MySQL
,并且该
.idb文件备份是干净的。有关创建干净备份的信息,请参见
第14.8.1.3节“移动或复制InnoDB表”。
第14.7.6节“将文件 - 表 - 表空间复制到另一个实例”中 概述的表空间复制限制 适用于此过程。
在新的MySQL实例上,重新创建具有相同名称的数据库中的表。
MySQL的>CREATE DATABASE sakila;MySQL的>USE sakila;MySQL的>CREATE TABLE actor (actor_id SMALLINT UNSIGNED NOT NULL AUTO_INCREMENT,first_name VARCHAR(45) NOT NULL,last_name VARCHAR(45) NOT NULL,last_update TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,PRIMARY KEY (actor_id),KEY idx_actor_last_name (last_name))ENGINE=InnoDB DEFAULT CHARSET=utf8;
放弃新创建的表格的表空间。
MySQL的> ALTER TABLE sakila.actor DISCARD TABLESPACE;
将.idb备份目录中的孤立文件复制到新的数据库目录。
外壳> cp /backup_directory/actor.ibd path/to/mysql-5.7/data/sakila/
确保.ibd文件具有必要的文件权限。
导入孤立.ibd文件。发出警告,指示InnoDB将尝试导入文件而无需模式验证。
MySQL的> ALTER TABLE sakila.actor IMPORT TABLESPACE; SHOW WARNINGS;
查询OK,0行受影响,1个警告(0.15秒)
警告| 1810 | InnoDB:IO读取错误:(2,没有这样的文件或目录)
打开“./sakila/actor.cfg”时出错,将尝试导入
没有模式验证
查询表格以验证.ibd
文件是否成功恢复。
MySQL的> SELECT COUNT(*) FROM sakila.actor;
+ ---------- +
| count(*)|
+ ---------- +
| 200 |
+ ---------- +
以下各项介绍了如何InnoDB
执行错误处理。InnoDB有时仅回滚失败的语句,有时回滚整个事务。
如果表空间中的文件空间
Table is full不足,则会发生MySQL
错误并
InnoDB回滚SQL语句。
一个事务死锁
导致InnoDB要
回滚整个
事务。发生这种情况时重试整个事务。
锁等待超时会导致InnoDB仅回滚等待锁的单个语句并遇到超时。(要使整个事务回滚,请使用该--innodb_rollback_on_timeout
选项启动服务器
。)如果使用当前行为,或者使用整个事务,请重试该语句
--innodb_rollback_on_timeout。
在繁忙的服务器上,死锁和锁等待超时都是正常的,应用程序必须知道它们可能发生并通过重试来处理它们。通过在事务和提交期间对数据进行的第一次更改之间尽可能少地工作,可以使它们变得不太可能,因此可以在尽可能短的时间内尽可能保持尽可能少的行数。有时,在不同的交易之间分工可能是实用而有用的。
由于死锁或锁定等待超时而发生事务回滚时,它会取消事务内语句的效果。但是,如果启动事务语句是
START
TRANSACTION或
BEGIN
语句,回滚不会取消该语句。进一步的SQL语句成为交易的一部分,直到发生COMMIT,
ROLLBACK或某些SQL语句导致隐式提交。
如果您没有IGNORE在语句中指定选项,则重复键错误会回滚SQL 语句。
A row too long error回滚SQL语句。
其他错误大多由MySQL层代码(在InnoDB存储引擎级别之上)检测到,并且它们回滚相应的SQL语句。锁不会在单个SQL语句的回滚中释放。
在隐式回滚期间,以及执行显式
ROLLBACKSQL语句期间,SHOW PROCESSLIST
显示相关连接Rolling back的
State列。